C应用程序中的内存分配

时间:2013-09-14 09:47:54

标签: c malloc calloc

我目前正在编写一个小应用程序来重新熟悉C(自从我上次写任何文章以来已经有一段时间了)和大多数人一样,我遇到了一个我无法弄清楚的内存分配问题。

代码围绕设置不同的面板,窗口和相关标题。确切地说,这是我遇到问题的标题字符串的内存分配。

基础是一个包含以下内容的结构:

struct TFB_PANEL
{
    WINDOW *window;
    char *title;
};

这在头文件中的typedef为:

typedef struct TFB_PANEL TfbPanel;

在相关的C文件中,我有以下方法初始化固定大小的数组TFB

int tfb_init()
{
    if (!_initialised) {
        return -1;
    }

    int i;
    for (i = 0; i < TYPE_MAX; i++) {
        TFB[i] = malloc(sizeof(TfbPanel*));
        TFB[i]->title = calloc((strlen(TYPES[i]) + 18), sizeof(char*));
        switch(i)
        {
            case A:
                sprintf(TFB[i]->title, " %s | r | h | s | t ", TYPES[i]);
                break;
            case B:
                sprintf(TFB[i]->title, " f | %s | h | s | t ", TYPES[i]);
                break;
            case C:
                sprintf(TFB[i]->title, " f | r | %s | s | t ", TYPES[i]);
                break;
            case D:
                sprintf(TFB[i]->title, " f | r | h | %s | t ", TYPES[i]);
                break;
            case E:
                sprintf(TFB[i]->title, " f | r | h | s | %s ", TYPES[i]);
                break;
        }

        TFB[i]->window = tfb_create_window(i);
    }
    return 0;
}

现在,初始化C时会发生错误。 A和B设置正确,长度为25个字符。另一方面,C在初始化后应该包含24个字符,而是(从tfb_create_window中)我收到

Program received signal EXC_BAD_ACCESS, Could not access memory
Reason: 13 at address 0x0000000000000000
0x00007fff930b9390 in strcmp()

检查堆栈显示TFB [C]正确初始化但标题元素不正确。这包含一个null元素,就好像我从未调用calloc一样。

请有人解释我在哪里出错或为什么A和B正确初始化但C杀了应用程序。一切都很美好,直到今天早上6点左右,从那时起它一直在下山。

如果有帮助,tfb_create_window的定义是调用_create_window并调用tfb_get_title,如下所示:

char *tfb_get_title(int type)
{
    if (type >= TFB_MAX) {
        return (char*)NULL;
    }
    return TFB[type]->title;
}

WINDOW *tfb_create_window(int type)
{
    int height = ((LINES - WIN_OFFSET_Y) / 3);
    char *title = tfb_get_title(type);
    return _create_window(height, WIN_SIDEBAR_X, WIN_OFFSET_Y, 0, COLOUR_MAIN, title);
}

WINDOW *_create_window(int height, int width, int starty, int startx, int color, const char *title)
{
    WINDOW *window;
    window = newwin(height, width, starty, startx);
    box(window, 0, 0);
    mvwprintw(window, 0, 2, title);
    wbkgd(window, COLOR_PAIR(color));
    return window;
}

2 个答案:

答案 0 :(得分:1)

此代码中存在许多错误,最严重的是,您使用sizeof(Type*)而不是sizeof(Type)。后者是对象的实际大小,第一个是指向该对象的指针的大小(在64位计算机上为8个字节)。

这意味着,malloc(sizeof(TfbPanel*))TfbPanel分配了太少的内存,因此程序的其余部分具有未定义的行为。

calloc()以同样的方式出错,但不加批判,因为你分配的内存是你需要的8倍。

但是,calloc()调用还有另一个错误:您在strlen()的结果中添加了18,这是您在sprintf()调用中添加的有效负载字符数。哪一个太少,因为strlen()的结果不包括空字节。

如果你可以使用符合POSIX-2008标准的libc(比如linux系统上的glibc),你可以使用asprintf()而不是sprintf(),它会自动为所得到的字符串提供足够的空间,避免任何可能的缓冲区大小错误如果您不能使用该功能,请至少使用snprintf()以避免访问未分配的内存。

答案 1 :(得分:0)

如果您使用gdb单步执行此行:

sprintf(TFB[i]->title, " f | r | %s | s | t ", TYPES[i]);

TYPES [i]的值是什么?