在C语言中模拟std::string.pop_back时字符串赋值后失效问题排查
问题分析与解决
首先,你的代码里有两个关键问题导致main函数里输出为空:
1. 局部数组out的生命周期问题
你在pop_back函数里定义的char out[stringLen];是栈上的局部变量,当函数执行完毕返回时,栈上的这块内存会被操作系统回收,不再属于你的程序。你把*string指向这块内存,回到main函数后,这个指针指向的是已经失效的内存区域,此时访问它属于未定义行为——有时候可能看似正常,有时候就会输出空或者乱码,这就是你遇到的情况。
2. 原字符串是只读常量的问题
另外,main函数里的char* string = "Hello World!";,这里的字符串是存储在程序的只读数据段中的,本质是一个常量。你不能直接修改它的内容,哪怕你想直接把最后一个字符改成'\0'也会触发内存访问错误。
修正方案
方案一:使用可写的字符数组(最简单高效)
把main里的字符串定义改成可写的字符数组,然后直接修改原数组的最后一个有效字符为'\0',不需要额外创建新数组:
#include <stdio.h> #include <string.h> void pop_back(char* string) { size_t stringLen = strlen(string); if (stringLen > 0) { // 避免空字符串的情况 string[stringLen - 1] = '\0'; } } int main(int argc, char* argv[]) { char string[] = "Hello World!"; // 这里是栈上的可写数组,不是只读常量 printf("Initial string: %s\n", string); pop_back(string); printf("After pop_back: %s\n", string); return 0; }
这个方案直接在原数组上修改,不需要额外内存,效率最高,也避免了指针失效的问题。
方案二:动态分配内存(适合原字符串是堆内存的场景)
如果你的原字符串是通过malloc分配的堆内存,那可以在pop_back里重新分配内存存储截断后的字符串,同时记得释放原内存避免泄漏:
#include <stdio.h> #include <string.h> #include <stdlib.h> void pop_back(char** string) { if (*string == NULL) return; size_t stringLen = strlen(*string); if (stringLen == 0) return; // 分配新内存,长度为原长度(原长度包含'\0',截断后长度是stringLen-1,加1存'\0') char* out = malloc(stringLen); if (out == NULL) { perror("malloc failed"); return; } strncpy(out, *string, stringLen - 1); out[stringLen - 1] = '\0'; // 手动添加结束符 free(*string); // 释放原内存 *string = out; } int main(int argc, char* argv[]) { // 把常量字符串复制到堆内存 char* string = strdup("Hello World!"); if (string == NULL) { perror("strdup failed"); return 1; } printf("Initial string: %s\n", string); pop_back(&string); printf("After pop_back: %s\n", string); free(string); // 最后记得释放堆内存 return 0; }
这个方案适合需要动态管理字符串的场景,比如字符串长度不固定、需要在函数间传递的情况。
内容的提问来源于stack exchange,提问作者fp.monkey
相关产品推荐
相关产品推荐

