c-指针需要比理论上更多的内存分配



对C来说还很陌生,但在最近遇到这个问题之前,我一直认为自己掌握了分配和管理内存的窍门。

我正在开发一个"make"实用程序。(这不是家庭作业,只是我朋友的旧作业,我认为我可以从中收集到有价值的练习。(我相信你们大多数人都知道,makefile有各种目标,在执行目标的命令之前,必须注意这些目标的依赖性。

为了存储在解析makefile时发现的给定目标依赖项的数据,我做了以下操作:

typedef struct{
    char* target;
    char** dependency_list;
}dependency_tracker;

为了跟踪多个dependency_trackers,我声明了(并随后为其分配(以下变量。(请注意"total_number_of_targets"后面的"+4"。没有它,程序就无法运行,我的问题是为什么会这样。(

dependency_tracker** d_tracker_ptr = (dependency_tracker**) malloc((total_number_of_targets+4)*sizeof(dependency_tracker*));

然后,我用以下行将指针发送到解析方法:

parse_file(filename,&d_tracker_ptr);

在parse_file函数中,我相信这些是我进行的最重要的调用(省略了字符串解析调用(。请注意,target_counter是迄今为止解析的目标数。我认为其他一切都应该是可以管理的:

dependency_tracker** tracker_ptr = *tracker_ptr_address; // tracker_ptr_address is the pointer I passed to the function above
// declare and allocate for the new struct we are creating
dependency_tracker* new_tracker_ptr = (dependency_tracker*) malloc(sizeof(dependency_tracker));
char* new_tracker_ptr_target = (char*) malloc((size_of_target)*sizeof(char)); // size_of_target is the string length
new_tracker_ptr->target = new_tracker_ptr_target;
*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = new_tracker_ptr;

正如我之前提到的,我必须为四个(dependency_tracker*(分配比我想象的更多的空间,才能在没有segfault的情况下完成这个程序。

我得出的结论是,这是因为我覆盖了为传递给parse_file的指针分配的空间。

我的问题是:为什么会发生这种情况?即使需要NULL指针的空间,也不需要4个额外指针的空间。如果我在对malloc 的原始调用中分配了任何少于25个额外字节的内容,那么程序就会产生segfault

如果有什么需要澄清的,请告诉我。我知道这有点像小说。

这是坏的:

*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = new_tracker_ptr;

指针大小由C决定。您需要:

tracker_ptr[target_counter] = new_tracker_ptr;

正如我在评论中提到的,您不允许在字符串中使用null终止符。

另一条评论:C不需要对malloc进行强制转换,使用强制转换会带来麻烦。此外,更安全的做法是取消引用您分配给sizeof的指针。所以只要说:

dependency_tracker *new_tracker_ptr = malloc(sizeof *new_tracker_ptr);
char* new_tracker_ptr_target = malloc(size_of_target * sizeof *new_tracker_ptr_target);
dependency_tracker *new_tracker_ptr =  malloc(*new_tracker_ptr);
new_tracker_ptr->target = new_tracker_ptr_target;

此外,您可能需要重新考虑变量名称中的空洞单词。事实上,我非常喜欢冗长的解释性标识符,但"tracker"one_answers"target"太模糊了,几乎没有增加清晰度。类似地,在变量名中嵌入类型信息a la _ptr在大约30年前还是一种时尚。现在一切都结束了。如果你有一个函数,声明和变量名不能在同一个屏幕上显示,那么这个函数太大了。

*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = ...

这就是问题所在。指针算术不是那样工作的。当使用正确类型(即不是char*(的指针算术时,不必乘以sizeof(anyhing)。更好的是,您根本不必使用指针算术。

tracker_ptr[target_counter] = ...

就是所需要的。

相关内容

  • 没有找到相关文章

最新更新