我正在摆弄C中的面向对象编程(注意!不是C ++或C# - 只是简单的' C)。现在,我试图动态调整结构的大小(我正在编写一个简单的String类)。代码构建正常:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct TestClass
{
char *s;
size_t size;
size_t b_size;
void (*CreateString) (struct TestClass*,char*);
};
void TestClassCreateString(struct TestClass *m, char* str)
{
char *buf;
m->size = strlen(str);
if (!m->size)
{
free(m->s);
m->s = malloc(16);
}
else
{
buf = realloc(m->s, m->size);
if (buf) m->s = buf;
}
}
struct TestClass* TestClassCreate()
{
struct TestClass* m = malloc((sizeof(struct TestClass)));
m->CreateString = TestClassCreateString;
return m;
}
int main()
{
struct TestClass* fizz = TestClassCreate();
fizz->CreateString(fizz,"Hello World");
free(fizz);
return 0;
}
...但是在运行它时我收到以下错误:
malloc: *** error for object 0x5000000000000000: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
是否有人能够确定我出错的地方?提前谢谢!
答案 0 :(得分:3)
malloc
不会将其记忆归零;它返回垃圾,因此你在struct
:
struct TestClass* m = malloc((sizeof(struct TestClass)));
答案 1 :(得分:1)
你很短1-byte
。如果您打算将1
复制到m->size
,则需要为{null}终止符str
添加m->s
。 E.g:
void TestClassCreateString(struct TestClass *m, char* str)
{
char *buf;
m->size = strlen(str);
if (!m->size)
{
free(m->s);
m->s = malloc(16);
}
else
{
buf = realloc(m->s, m->size + 1);
if (buf) m->s = buf;
strncpy (m->s, str, m->size + 1);
}
}
然后你可以做类似的事情:
int main()
{
struct TestClass* fizz = TestClassCreate();
fizz->CreateString(fizz,"Hello World");
printf ("\n fizz->s : %s\n\n", fizz->s);
free(fizz);
return 0;
}
并获得:
$ ./bin/oo_struct
fizz->s : Hello World
答案 2 :(得分:1)
在struct TestClass
中创建TestClassCreate()
时,代码会错过正确初始化新分配的struct
。
所以打电话
free(m->s);
尝试在随机地址释放内存,该地址调用未定义的行为并且通常会使程序崩溃。
要解决此问题,请按以下步骤修改代码
struct TestClass* TestClassCreate()
{
struct TestClass* m = ...
...
m->s = NULL;
m->size = 0;
m->b_size = 0;
return m;
}
为了让事情变得更好,还要添加一些错误检查:
struct TestClass* TestClassCreate()
{
struct TestClass * m = malloc((sizeof(struct TestClass)));
if (NULL != m)
{
m->CreateString = TestClassCreateString;
m->s = NULL;
m->size = 0;
m->b_size = 0;
}
return m;
}
要使代码更加自动防故障,请应用这些最后的更改:
struct TestClass* TestClassCreate(void)
{
struct TestClass * m = malloc(sizeof *m);
...
更多的代码错过了在这里为C-“string”的0
- 终结符分配内存:
void TestClassCreateString(struct TestClass *m, char* str)
{
...
else
{
buf = realloc(m->s, m->size + 1); /* allocate 1 byte more for the trailing
`0` marking the end of a C-"string". */
...