在C中动态调整结构大小

时间:2015-10-14 16:05:22

标签: c struct

我正在摆弄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

是否有人能够确定我出错的地方?提前谢谢!

3 个答案:

答案 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". */
    ...