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

C 指针需要比理论上更多的内存分配,c,memory,segmentation-fault,malloc,C,Memory,Segmentation Fault,Malloc,对于C语言来说,这是一个相当新的概念,但我认为我已经掌握了分配和管理内存的窍门,直到最近我遇到了这个问题 我正在开发一个“make”实用程序。(这不是家庭作业,只是我朋友的旧作业,我想我可以从中收集到有价值的练习。)我相信你们大多数人都知道,makefile有各种目标,这些目标有一些在执行目标命令之前必须注意的细节 为了存储解析makefile时发现的给定目标依赖项的数据,我做了以下操作: typedef struct{ char* target; char** dependen

对于C语言来说,这是一个相当新的概念,但我认为我已经掌握了分配和管理内存的窍门,直到最近我遇到了这个问题

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

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

typedef struct{
    char* target;
    char** dependency_list;
}dependency_tracker;
为了跟踪多个依赖项跟踪程序,我声明(并随后分配)以下变量。(请注意“目标总数”后面的“+4”。没有它,程序无法运行,我的问题是为什么会这样。)

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

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*)分配空间,这比我想象的要多,这样程序才能顺利完成

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

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

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

*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = ...
这就是问题所在。不是那样的。使用正确键入的(即非
char*
)指针算法时,不必乘以
sizeof(anyhing)
。更好的是,您根本不必使用指针算法

tracker_ptr[target_counter] = ...
这就是所需要的

这就是问题所在。不是那样的。使用正确键入的(即非
char*
)指针算法时,不必乘以
sizeof(anyhing)
。更好的是,您根本不必使用指针算法

tracker_ptr[target_counter] = ...
这就是所需的一切。

这是坏的:

*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = new_tracker_ptr;
指针大小由C计算。您需要:

tracker_ptr[target_counter] = new_tracker_ptr;
正如我在评论中提到的,您不允许在字符串中使用空终止符

另一条评论: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;
此外,您可能需要重新考虑变量名中的空洞词。事实上,我非常喜欢冗长的解释性标识符,但“跟踪器”和“目标”太模糊了,它们几乎没有增加清晰度。类似地,在变量名中嵌入类型信息大约在30年前是一种时尚。现在结束了。如果您有一个不能在同一屏幕上搜索声明和变量名的函数,则该函数太大。

这是错误的:

*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = new_tracker_ptr;
指针大小由C计算。您需要:

tracker_ptr[target_counter] = new_tracker_ptr;
正如我在评论中提到的,您不允许在字符串中使用空终止符

另一条评论: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;

此外,您可能需要重新考虑变量名中的空洞词。事实上,我非常喜欢冗长的解释性标识符,但“跟踪器”和“目标”太模糊了,它们几乎没有增加清晰度。类似地,在变量名中嵌入类型信息大约在30年前是一种时尚。现在结束了。如果您有一个函数,其中声明和变量名不能在同一屏幕上搜索,则该函数太大。

如果您使用的是正常的
\0
终止的C字符串,则忘记分配一个字节来保存该终止字符。Gene,您是对的。谢谢如果您使用的是正常的
\0
终止的C字符串,那么您忘记分配一个字节来保存该终止字符。Gene,您是对的。谢谢如果我真的想使用指针算法,那么我需要什么呢?就*(跟踪器+目标计数器)=…?好的,非常感谢。如果我真的想使用指针算法,那么我需要什么?只有*(tracker\u ptr+target\u counter)=…?好的,非常感谢。为什么取消指针引用比使用类型更安全?是否会出现这样一种情况,即两者提供不同的值,或者是为了防止自己在其中输入错误的类型?@lane0335这是一件枯燥的事情。如果更改指针的类型,并且类型名称也在
sizeof
中使用,则还需要记住更改第二个副本。如果你省略了这个错误,编译器就不会发现它。使用取消引用的指针,犯错误的机会就少了一次。为什么取消引用指针比使用类型更安全?是否会出现这样一种情况,即两者提供不同的值,或者是为了防止自己在其中输入错误的类型?@lane0335这是一件枯燥的事情。如果更改指针的类型,并且类型名称也在
sizeof
中使用,则还需要记住更改第二个副本。如果你省略了这个错误,编译器就不会发现它。有了这一点,犯错误的机会就少了一次。