user-0 提问: 有关malloc和free的一个问题

回复:
user: user-1
content: 注意这里 fgets(tmp->trans[0],1024,fp);

user: user-2
content: printf("%d\n", sizeof(char*));

user: user-0
content: 引用 23 楼 wang0635 的回复：[quote=引用 19 楼 juge0007 的回复:] [quote=引用 18 楼 wang0635 的回复:] 至少这几个地方是有隐患的     p = (word_t **)malloc(sizeof(word_t)); ======>>>>>> p = (word_t **)malloc(sizeof(word_t *));     fp = fopen("dict.txt", "r");	//打开文件dict.txt，只读     if(!fp)     {         puts("数据库文件不存在!");         return 0;     }      word_t *tmp = (word_t *)malloc(sizeof(word_t));     tmp->key = (char *)malloc(100);     tmp->trans = (char **)malloc(sizeof(char **)); ======>>>>>> tmp->trans = (char **)malloc(sizeof(char *));     tmp->trans[0] = (char *)malloc(256 * sizeof(char *));  ======>>>>>> tmp->trans[0] = (char *)malloc(256 * sizeof(char));  里面的sizeof我换成了数字程序就会崩溃[/quote]你把里面sizeof的结果打印出来看看跟你换成的数字是否一样。为什么要用数字呢？老师没有提醒过吗[/quote]一样的，我编译器里sizeof char*也是四个字节

user: user-0
content: 引用 30 楼 ofof2008 的回复：sizeof()是编译器会算出来的，感觉应该不是这里的问题。确实是包含了sizeof就一点问题也没有了

user: user-0
content: 引用 24 楼 liulilittle 的回复：你破坏掉了 malloc 分配的内存块的尾部。什么意思？怎么破坏的啊？

user: user-3
content: sizeof()是编译器会算出来的，感觉应该不是这里的问题。

user: user-4
content: 我稍稍修改了下你贴的源码，在dict.txt贴了一大段英文，让程序跑起来，然后照你说的将tmp->trans[0] = (char *)malloc(256 * sizeof(char *))修改为tmp->trans[0] = (char *)malloc(1024)，就是把sizeof(char*)换成了4，在windows 32位下codeblocks，以及linux 64位下gcc，运行都没有报错。你确定就是这里的问题吗？看这个源代码，貌似应该还有其他关联的源码（结构体啊之类的），是否问题出在其他地方呢？另外，要么就是功能性的问题了，处理字符串的确有可能越界。我也没招了。以下是我瞎改的测试源代码#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h>  #define KEYSIZE 100 #define MAXSIZE 1024  typedef struct{     char *key;     char **trans;     int n;  }word_t;  word_t **p; int pos = 0; int alpha = 0;  void insert_array(word_t *,int);   int read_txtfile(void) {     FILE *fp;      p = (word_t **)malloc(sizeof(word_t *));     printf("sizeof word_t = %d\n",sizeof(word_t));//我瞎编的结构体，windows32位运行结果是12，linux 64位运行结果是24     printf("sizeof word_t* = %d\n",sizeof(word_t *));//windows32位运行结果是4，linux 64位运行结果是8     printf("sizeof char = %d\n",sizeof(char));//windows32位运行结果是1，linux 64位运行结果当然也是1     printf("sizeof char* = %d\n",sizeof(char *));//windows32位运行结果是4，linux 64位运行结果是8     printf("sizeof char ** = %d\n",sizeof(char **));//windows32位运行结果是4，linux 64位运行结果是8      fp = fopen("dict.txt", "r");	//打开文件dict.txt，只读     if(!fp)     {         puts("数据库文件不存在!");         return 0;     }      word_t *tmp = (word_t *)malloc(sizeof(word_t));     tmp->key = (char *)malloc(KEYSIZE+1);     tmp->trans = (char **)malloc(sizeof(char *) * 1);     tmp->trans[0] = (char *)malloc(MAXSIZE * 1);      while(fgets(tmp->key,KEYSIZE,fp))     {          fgets(tmp->trans[0],MAXSIZE,fp);	//单词解释中@前后没有换行符，所以将整个解释读入了trans[0]中         insert_array(tmp,pos);         pos++;      }      free(tmp->trans[0]);     free(tmp->trans);     free(tmp->key);     free(tmp);     fclose(fp);      return 1; }  void insert_array(word_t *tmp,int pos) {     extern word_t **p;     int count = 0;     //word_t **temp_ads = NULL;      if(*(tmp->key + strlen(tmp->key) - 1) == '\n')         *(tmp->key + strlen(tmp->key) - 1) = '\0';     if(*(tmp->trans[0] + strlen(tmp->trans[0]) - 1) == '\n')         *(tmp->trans[0] + strlen(tmp->trans[0]) - 1) = '\0';      p = (word_t **)realloc(p, sizeof(word_t*) * (pos + 1));      p[pos] = (word_t *)malloc(sizeof(word_t));     p[pos]->key = (char *)malloc(strlen(tmp->key) + 1);      strcpy(p[pos]->key,tmp->key + 1);	//读入字符串第一位是#，所以从key+1开始拷贝      if(tolower(*p[pos]->key) >= 'a' && tolower(*p[pos]->key) <= 'z')         alpha++;      char str[1024];     strcpy(str,tmp->trans[0]);     char *token = strtok(str,";");	//将文本中的Trans过滤掉     p[pos]->trans = NULL;      while((token = strtok(NULL,"@")))	//将@以前Trans以后的内容放入token中     {         p[pos]->trans = (char **)realloc(p[pos]->trans, sizeof(char *) * (count + 1));	//调整指针的大小,每个指针大小为4         p[pos]->trans[count] = (char *)malloc(strlen(token) + 1);         strcpy(p[pos]->trans[count],token);         count++;     }      p[pos]->n = count; }  int main() {     read_txtfile();     return 0; }

user: user-5
content: 先打印sizeof(char *)，再用打印出来数字替换，如果还是有问题，清空整个工程再试试，或换编译器试试。如果不同编译器都是sizeof(char *) OK，sizeof(数字)有问题，那只能有请楼下大神了

user: user-6
content: 这个上下两个都是一样的，看着没有问题

user: user-7
content: 你破坏掉了 malloc 分配的内存块的尾部。

user: user-8
content: 引用 19 楼 juge0007 的回复:[quote=引用 18 楼 wang0635 的回复:] 至少这几个地方是有隐患的     p = (word_t **)malloc(sizeof(word_t)); ======>>>>>> p = (word_t **)malloc(sizeof(word_t *));     fp = fopen("dict.txt", "r");	//打开文件dict.txt，只读     if(!fp)     {         puts("数据库文件不存在!");         return 0;     }      word_t *tmp = (word_t *)malloc(sizeof(word_t));     tmp->key = (char *)malloc(100);     tmp->trans = (char **)malloc(sizeof(char **)); ======>>>>>> tmp->trans = (char **)malloc(sizeof(char *));     tmp->trans[0] = (char *)malloc(256 * sizeof(char *));  ======>>>>>> tmp->trans[0] = (char *)malloc(256 * sizeof(char));  里面的sizeof我换成了数字程序就会崩溃[/quote]你把里面sizeof的结果打印出来看看跟你换成的数字是否一样。为什么要用数字呢？老师没有提醒过吗

user: user-9
content: 引用 13 楼 shihengzhen101 的回复:32位程序没有任何区别，但是64位上指针就是8个字节了，大小就有所不同 感觉是空间没申请够，将1024改成2048试试

user: user-9
content: 32位程序没有任何区别，但是64位上指针就是8个字节了，大小就有所不同

user: user-10
content: 申請空間盡量避免直接指明數字，這不是個好習慣啊

user: user-11
content: 引用 6 楼 juge0007 的回复:[quote=引用 4 楼 zangfong 的回复：]sizeof(char *)在64位系统下应该是8个字节吧，32位系统是4个字节。 在32位系统中，只是将tmp->trans[0] = (char *)malloc(1024)修改成tmp->trans[0] = (char *)malloc(256 * sizeof(char *))提高了程序的可读性和可移植性，不应该影响最后的free。 如果free出错，个人感觉还是动了tmp->trans[0]，没有指向申请内存的首地址，或者是free了两次。  另外，不管怎样，动态申请内存，还是带上sizeof更好。我明天试试[/quote] 我觉得跟系统的位数无关，64位char*虽然占8字节，32位占4字节，但是我同样申请1024空间一样，管它是多少位的，只要是4的倍数，就可以正常存储数据。那么他说到free的时候有问题，所以基本可以确定是trans[0]这有问题，释放的时候不是释放的首地址。这样的问题贴点源码上来看一看，分析分析呀。

user: user-12
content: 为什么要用数组指向一个地址空间呢

user: user-8
content: 指针的长度，最好不要假设与int一样。有的机器上是3字节的呢（keil C51）

user: user-13
content: 64位下指针长度是8字节，32位下指针长度是4字节 或者你自己printf下sizeof(char *)的值不就好了 一定要多调试，而不是脑补

user: user-14
content: 引用 4 楼 zangfong 的回复:sizeof(char *)在64位系统下应该是8个字节吧，32位系统是4个字节。 在32位系统中，只是将tmp->trans[0] = (char *)malloc(1024)修改成tmp->trans[0] = (char *)malloc(256 * sizeof(char *))提高了程序的可读性和可移植性，不应该影响最后的free。 如果free出错，个人感觉还是动了tmp->trans[0]，没有指向申请内存的首地址，或者是free了两次。  另外，不管怎样，动态申请内存，还是带上sizeof更好。 64位的程序是8字节 64位系统 32位程序是4字节

user: user-13
content: 叫不醒一个装睡的楼主