我在GTK应用程序中有类似的代码(但范围更大):

#include <stdio.h>

struct TStruct {
    char *string;
}

void func(struct TStruct *tstruct) {
    char chara[8];
    sprintf(chara, "%.*s", 4, "testing");
    tstruct->string = chara;
}

int  main() {
    struct TStruct tstruct;
    tstruct.string = NULL;
    func(&tstruct);
    printf("%s", tstruct.string);
    return 0;
}

这段代码本身工作得很好.但是,在GTK应用程序中,在代码段之后的任何位置创建GTK对象都会损坏tstruct.string的值.为什么会这样呢?上面的代码片段不是分配字符串的最佳方式吗?

tstruct->string = chara更改为tstruct->string = g_strdup(chara)可以解决该问题.我可以猜到这就是问题所在,但有谁能解释一下它是如何工作的吗?

推荐答案

你需要注意你正在做的事情.您在堆栈中分配了一个char数组,因为它是func函数的本地数组,并且您将它们分配给作为参数传递的 struct 的一个成员.你有一些 Select 来解决你的问题.一种方法是使用char数组而不是指向char的指针,并完全复制该数组:

#include <stdio.h>
#include <string.h>

#define STRING_SIZE 8

struct TStruct {
    char string[STRING_SIZE];
};

void func(struct TStruct *tstruct) {
    char chara[STRING_SIZE];
    sprintf(chara, "%.*s", 4, "testing");
    strncpy( tstruct->string, chara, STRING_SIZE );
}

int main() {
    struct TStruct tstruct = {0};
    func(&tstruct);
    printf("%s", tstruct.string);
    return 0;
}

另一种方法是动态分配内存,然后释放内存:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STRING_SIZE 8

struct TStruct {
    char *string;
};

void func(struct TStruct *tstruct) {
    char *chara = (char*) malloc( STRING_SIZE * sizeof(char) );
    sprintf(chara, "%.*s", 4, "testing");
    tstruct->string = chara;
}

void freeTStruct( struct TStruct *tstruct ) {
    free( tstruct->string );
}

int main() {
    struct TStruct tstruct = {0};
    func(&tstruct);
    printf("%s", tstruct.string);
    freeTStruct(&tstruct);
    return 0;
}

最后,我将实现如下内容:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct MyType {
    char *string;
    size_t stringLength;
} MyType;

MyType newMyType( const char* string ) {

    MyType new = {
        .string = NULL,
        .stringLength = strlen(string)
    };

    new.string = (char*) malloc( (new.stringLength+1) * sizeof(char) );
    strncpy( new.string, string, new.stringLength+1 );

    return new;

}

void freeMyType( MyType *myType ) {
    free( myType->string );
}

int main() {
    MyType foo = newMyType( "bar" );
    printf( "string: \"%s\", length: %d", foo.string, foo.stringLength );
    freeMyType( &foo );
    return 0;
}

C++相关问答推荐

为指针 struct 创建宏

有什么方法可以检测SunOS上的SparcWorks吗?

使用NameSurname扫描到两个单独的字符串

CSAPP微型shell 实验室:卡在sigprocmask

FRIDA-服务器成为端口扫描的目标?

为什么指针运算会产生错误的结果?

cairo 剪辑区域是否存在多个矩形?

为什么Fread()函数会读取内容,然后光标会跳到随机位置?

致命错误:ASM/rwan ce.h:没有这样的文件或目录.符号链接还不够

Tic-tac-toe:从文件加载存储

Caesar密码调试:输出文本末尾的问号和随机字符

为什么WcrTomb只支持ASCII?

从不兼容的指针类型返回&&警告,但我看不出原因

如何对现有的双向循环链表进行排序?

强制GCC始终加载常量(即只读),即使启用了优化

意外的C并集结果

当读取可能会阻塞管道中的父进程时,为什么要等待子进程?

I';我试着从.txt文件中读取文本,并用c计算其中的单词数量

将指针的地址加载到寄存器内联拇指组件中

malloc:损坏的顶部大小无法找出问题