有关malloc和free的一个问题

juge0007 2018-08-29 11:08:29
请问一下,我在malloc的时候使用
tmp->trans[0] = (char *)malloc(1024)来申请空间,后面对tmp->trans[0]进行free时就会报错,
但是我用
tmp->trans[0] = (char *)malloc(256 * sizeof(char *)),来申请空间的话,后面用free时就不会报错,
这是为什么呢?sizeof(char *)不就是四个字节吗,256 * 4 == 1024,这两种写法不是一样的吗?怎么前一种方法free时会出错,
带上sizeof就没有问题了呢?
...全文
979 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
老夏 2018-09-11
  • 打赏
  • 举报
回复
注意这里 fgets(tmp->trans[0],1024,fp);
ForestDB 2018-09-06
  • 打赏
  • 举报
回复
printf("%d\n", sizeof(char*));
juge0007 2018-09-01
  • 打赏
  • 举报
回复
引用 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*也是四个字节
juge0007 2018-09-01
  • 打赏
  • 举报
回复
引用 30 楼 ofof2008 的回复:
sizeof()是编译器会算出来的,感觉应该不是这里的问题。
确实是包含了sizeof就一点问题也没有了
juge0007 2018-09-01
  • 打赏
  • 举报
回复
引用 24 楼 liulilittle 的回复:
你破坏掉了 malloc 分配的内存块的尾部。
什么意思?怎么破坏的啊?
ofof2008 2018-09-01
  • 打赏
  • 举报
回复
sizeof()是编译器会算出来的,感觉应该不是这里的问题。
zangfong 2018-09-01
  • 打赏
  • 举报
回复
我稍稍修改了下你贴的源码,在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;
}
啊大1号 2018-08-31
  • 打赏
  • 举报
回复
先打印sizeof(char *),再用打印出来数字替换,如果还是有问题,清空整个工程再试试,或换编译器试试。如果不同编译器都是sizeof(char *) OK,sizeof(数字)有问题,那只能有请楼下大神了
aytx 2018-08-31
  • 打赏
  • 举报
回复
这个上下两个都是一样的,看着没有问题
liulilittle 2018-08-31
  • 打赏
  • 举报
回复
你破坏掉了 malloc 分配的内存块的尾部。
wang0635 2018-08-31
  • 打赏
  • 举报
回复
引用 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的结果打印出来看看跟你换成的数字是否一样。为什么要用数字呢?老师没有提醒过吗
AlbertS 2018-08-30
  • 打赏
  • 举报
回复
引用 13 楼 shihengzhen101 的回复:
32位程序没有任何区别,但是64位上指针就是8个字节了,大小就有所不同

感觉是空间没申请够,将1024改成2048试试
AlbertS 2018-08-30
  • 打赏
  • 举报
回复
32位程序没有任何区别,但是64位上指针就是8个字节了,大小就有所不同
老马何以识途 2018-08-30
  • 打赏
  • 举报
回复
申請空間盡量避免直接指明數字,這不是個好習慣啊
离水的鱼儿 2018-08-30
  • 打赏
  • 举报
回复
引用 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]这有问题,释放的时候不是释放的首地址。这样的问题贴点源码上来看一看,分析分析呀。
chncpj 2018-08-30
  • 打赏
  • 举报
回复
为什么要用数组指向一个地址空间呢
wang0635 2018-08-30
  • 打赏
  • 举报
回复
指针的长度,最好不要假设与int一样。有的机器上是3字节的呢(keil C51)
636f6c696e 2018-08-30
  • 打赏
  • 举报
回复
64位下指针长度是8字节,32位下指针长度是4字节
或者你自己printf下sizeof(char *)的值不就好了
一定要多调试,而不是脑补
cjzzmdn 2018-08-30
  • 打赏
  • 举报
回复
引用 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字节
636f6c696e 2018-08-30
  • 打赏
  • 举报
回复
叫不醒一个装睡的楼主
加载更多回复(12)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧