结构体指针赋值后仍为NULL的技术问题求助
问题分析与解决方案
核心原因:C语言的参数值传递
你遇到的问题本质是C语言中函数参数的传递是值传递——当你把partitioned(一个Tuple*类型的指针)传给get_name_field时,函数内部会创建一个这个指针的副本。你在函数里对这个副本做的赋值(partitioned = split_prefix(...))只会修改副本的值,完全不会影响外部的partitioned变量。这就是为什么调试时split_prefix返回了有效的指针,但外部的partitioned依然是NULL。
解决方案:传递二级指针(最直接的修复方式)
要让函数能修改外部的指针变量,你需要传递指针的指针(也就是Tuple**),这样函数内部可以通过解引用操作修改外部指针的指向。
修改get_name_field函数
// 获取名称字段,成功返回TRUE,失败返回FALSE int get_name_field(Tuple **partitioned, char name_field[], char *fname, char *cwd, int cwd_len) { // fname无法拆分 if (strlen(fname) > 155) { perror(fname); return FALSE; } // 存在路径(前缀) else if (cwd) { // fname字段长度不足 if (strlen(cwd) + 1 + strlen(fname) > 100) { // ***********修改赋值位置************** if ((*partitioned = split_prefix(cwd, strlen(cwd))) == NULL) { perror("partition failed"); return FALSE; } memcpy(name_field, (*partitioned)->part1, strlen((*partitioned)->part1)); } // ... 剩余代码保持不变 } // ... 剩余代码保持不变 }
修改测试函数的调用
void test_get_name_field3(void) { Tuple *partitioned = NULL; char name_field[NAME_LEN] = {'\0'}; char *fname = "hellobutunfortunatelythiswon'tfit.txt"; char *cwd = "user/bin/arafian/ratherlongdirectorynameandwillnot/fitin" "thenamefieldonlysoitwilloverflowtotheprefixfield"; int cwd_len = strlen(cwd); // 传递指针的地址 get_name_field(&partitioned, name_field, fname, cwd, cwd_len); char *result = "user/bin/arafian/ratherlongdirectorynameandwillnot/"; checkit_string(name_field, result); // 现在partitioned指向了分配的内存,可以正确free if (partitioned != NULL) { free(partitioned); } }
另一种方案:让函数返回指针
如果你觉得二级指针不够直观,也可以调整get_name_field的设计,让它直接返回Tuple*指针,同时用返回值的特殊状态来表示操作是否成功:
// 返回拆分后的Tuple指针,失败返回NULL;name_field会被填充成功的前缀 Tuple* get_name_field(char name_field[], char *fname, char *cwd, int cwd_len) { // fname无法拆分 if (strlen(fname) > 155) { perror(fname); return NULL; } // 存在路径(前缀) else if (cwd) { // fname字段长度不足 if (strlen(cwd) + 1 + strlen(fname) > 100) { Tuple *partitioned = split_prefix(cwd, strlen(cwd)); if (partitioned == NULL) { perror("partition failed"); return NULL; } memcpy(name_field, partitioned->part1, strlen(partitioned->part1)); return partitioned; } // ... 剩余逻辑:处理不需要拆分的情况,返回NULL或者相应的值 } return NULL; }
对应的测试函数调用修改为:
void test_get_name_field3(void) { char name_field[NAME_LEN] = {'\0'}; char *fname = "hellobutunfortunatelythiswon'tfit.txt"; char *cwd = "user/bin/arafian/ratherlongdirectorynameandwillnot/fitin" "thenamefieldonlysoitwilloverflowtotheprefixfield"; int cwd_len = strlen(cwd); Tuple *partitioned = get_name_field(name_field, fname, cwd, cwd_len); char *result = "user/bin/arafian/ratherlongdirectorynameandwillnot/"; checkit_string(name_field, result); if (partitioned != NULL) { free(partitioned); } }
额外注意事项
- 内存泄漏:原来的代码中,
split_prefix分配的内存会因为外部指针没拿到而泄漏,修复后要确保在使用完partitioned后调用free。 - 边界检查:确保
memcpy操作不会越界,比如在split_prefix中,要保证i+1不超过NAME_LEN,cwd_len - i -1不超过PREFIX_LEN,避免缓冲区溢出。
内容的提问来源于stack exchange,提问作者dumbitdownjr
相关产品推荐
相关产品推荐

