C应用程序中的内存分配

C应用程序中的内存分配,c,malloc,calloc,C,Malloc,Calloc,我目前正在编写一个小应用程序来重新熟悉C语言(我上次编写C语言已经有一段时间了),和大多数人一样,我遇到了一个无法解决的内存分配问题 代码围绕不同面板、窗口和相关标题的设置展开。确切地说,这是我遇到问题的标题字符串的内存分配 底座是一个结构,包含: struct TFB_PANEL { WINDOW *window; char *title; }; 这在头文件中的类型定义为: typedef struct TFB_PANEL TfbPanel; 在相关的C文件中,我使用以下方

我目前正在编写一个小应用程序来重新熟悉C语言(我上次编写C语言已经有一段时间了),和大多数人一样,我遇到了一个无法解决的内存分配问题

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

底座是一个结构,包含:

struct TFB_PANEL
{
    WINDOW *window;
    char *title;
};
这在头文件中的类型定义为:

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;
}
检查堆栈显示TFB[C]已正确初始化,但title元素未正确初始化。这包含一个null元素,就好像我从未调用过calloc一样

请有人解释一下我在这方面哪里出了问题,或者为什么A和B的初始化正确,但C却终止了应用程序。直到今天早上6点左右,一切都进行得很顺利,从那时起就一直在走下坡路

如果有帮助,
tfb\u create\u window
通过调用
\u create\u window
和调用
tfb\u get\u 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;
}

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

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

类型[i]的值是多少?

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

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

calloc()
也有同样的错误,但并不重要,因为您分配的内存是所需内存的八倍

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


如果您可以使用兼容POSIX-2008的libc(如linux系统上的glibc),那么您可以使用
asprintf()
而不是
sprintf()
,它将自动为生成的字符串分配足够的空间,从而避免任何可能的缓冲区大小错误。如果您不能使用该函数,请至少使用
snprintf()
以避免访问未分配的内存。

这不是您的问题,但请注意,您实际上在某一点上分配了太多内存:
calloc((strlen(TYPES[i])+18),sizeof(char*)
。这为
(strlen(TYPES[i])+18
字符指针分配了空间,这可能是您真正需要的内存的4到8倍。我也这么认为,我最初只分配
strlen(TYPES[i])+18
,但我在尝试修复它的同时添加了乘数。我还尝试使用
malloc(strlen(TYPES[i])+18)
但是没有用。@mplf您确定要这样做而不是
malloc(sizeof(TfbPanel*)
)。还有什么是
TFB[i]
?TfbPanel的内存不是问题,无论我以何种方式为面板分配内存,我仍然从字符串比较中获得完全相同的错误访问信号。
TFB[I]
是指向有效内存块的指针,在我添加动态标题之前,该内存块一直工作正常。
TFB
数组定义为:
TfbPanel*TFB[TYPE_MAX]
我的意思是您希望指针的大小为
TfbPanel
对象的大小?TYPES是一个固定数组,定义为char*TYPE[]={“feature”,“release”,hotfix,support,trunk“};
TYPE_MAX
的值是多少?
enum
的范围是A-TYPE_MAX,对应于类型数组中的键值基于到目前为止的注释,我已经交换了
malloc(sizeof(TfbPanel*)
的赋值以使用
malloc(sizeof(struct TfbPanel))
-正如您正确指出的,关键问题是字符串中的字符太少。我已将此添加到中,并已解决。谢谢。
sprintf(TFB[i]->title, " f | r | %s | s | t ", TYPES[i]);