C 使用指针的分段故障(堆芯转储)

C 使用指针的分段故障(堆芯转储),c,string,pointers,segmentation-fault,C,String,Pointers,Segmentation Fault,当我构建下面的代码时,我得到了输出 Mystr分段故障(堆芯转储) 我猜是strNULL和set函数导致了错误。。 我猜是赖特吗 我不知道怎么了。 请告诉我出了什么问题以及如何解决。 如果建议我的编码风格:D,我将不胜感激 globalcall.c(声明的全局指针) string1.h(头文件) string.c #include <stdlib.h> #include "string1.h" extern string *call; int _string_compare

当我构建下面的代码时,我得到了输出

Mystr
分段故障(堆芯转储)

我猜是strNULL和set函数导致了错误。。 我猜是赖特吗

我不知道怎么了。 请告诉我出了什么问题以及如何解决。
如果建议我的编码风格:D,我将不胜感激

globalcall.c(声明的全局指针)

string1.h(头文件)



string.c

#include <stdlib.h>
#include "string1.h"

extern string *call;

int _string_compare(string *target);
string *_string_set(string *target);

string *new_string(const char *str){
    string *ptr;
    int i = 0;

    ptr = (string *)malloc(sizeof(string));
    if(ptr == 0){
        return 0;
    }

    ptr->str = 0;
    ptr->len = 0;

    ptr->compare = _string_compare;
    ptr->set = _string_set;

    if(str){
        for(ptr->len = 0;str[ptr->len];ptr->len++);

        ptr->str = (char *)malloc(ptr->len + 1);

        if(ptr->str == 0){
            free(ptr);
            return 0;
        }
        for(i = 0;i<ptr->len + 1;i++){
            ptr->str[i] = str[i];
        }
    } else {
        ptr->str = (char *)malloc(1);
        ptr->str = 0;
    }

    return ptr;
}

void delete_string(string *str){
    if(str->str != 0){
        free(str->str);
        str->str = 0;
    }
    free(str);

    return;
}

int _string_compare(string *target){
    int i = 0;
    if(call->len != target->len){
        return 0;
    } else {
        for(i=0;i<call->len;i++){
            if(call->str[i] != target->str[i]){
                return 0;
            }
        }
    }
    return 1;
}

string *_string_set(string *target){
    int i = 0;

    free(call->str);
    call->str = (char *)malloc(call->len+1);

    for(i = 0;i<call->len;i++){
        call->str[i] = target->str[i];
    }

    call->len = target->len;

    return call;
}
#包括
#包括“string1.h”
外部字符串*调用;
整数字符串比较(字符串*目标);
字符串*字符串集合(字符串*目标);
字符串*新字符串(常量字符*字符串){
字符串*ptr;
int i=0;
ptr=(字符串*)malloc(sizeof(字符串));
如果(ptr==0){
返回0;
}
ptr->str=0;
ptr->len=0;
ptr->compare=\u string\u compare;
ptr->set=\u字符串\u集合;
如果(str){
for(ptr->len=0;str[ptr->len];ptr->len++);
ptr->str=(char*)malloc(ptr->len+1);
如果(ptr->str==0){
免费(ptr);
返回0;
}
对于(i=0;ilen+1;i++){
ptr->str[i]=str[i];
}
}否则{
ptr->str=(char*)malloc(1);
ptr->str=0;
}
返回ptr;
}
无效删除_字符串(字符串*str){
如果(str->str!=0){
自由(str->str);
str->str=0;
}
自由基(str);
返回;
}
整数字符串比较(字符串*目标){
int i=0;
如果(调用->len!=目标->len){
返回0;
}否则{
对于(i=0;ilen;i++){
如果(调用->str[i]!=目标->str[i]){
返回0;
}
}
}
返回1;
}
字符串*\u字符串\u集(字符串*目标){
int i=0;
免费(呼叫->str);
call->str=(char*)malloc(call->len+1);
对于(i=0;ilen;i++){
调用->str[i]=目标->str[i];
}
调用->len=目标->len;
回电;
}


主文件

typedef struct tag_string{
    char *str;
    unsigned int len;

    int (*compare)(struct tag_string *target);
    struct tag_string *(*set)(struct tag_string *target);
} string;

string *new_String(const char *str);
void delete_string(string *str);
#include <stdio.h>
#include "string1.h"

extern void *call;

int main(void) {
    string *mystr = new_string("Mystr");
    string *strNULL = new_string(0);

    printf("%s\n",mystr->str);
    printf("%s\n",strNULL->str);

    if(strNULL->set(mystr)->compare(mystr)){
        printf("Compare : TRUE!");
    }

    printf("%s\n",mystr->str);
    printf("%s\n",strNULL->str);

    delete_string(mystr);
    delete_string(strNULL);

    return 0;
}
#包括
#包括“string1.h”
外部无效*调用;
内部主(空){
字符串*mystr=新字符串(“mystr”);
字符串*strNULL=新字符串(0);
printf(“%s\n”,mystr->str);
printf(“%s\n”,strNULL->str);
如果(strNULL->set(mystr)->比较(mystr)){
printf(“比较:真!”);
}
printf(“%s\n”,mystr->str);
printf(“%s\n”,strNULL->str);
删除_字符串(mystr);
删除字符串(strNULL);
返回0;
}

这是一个非常简单的问题,但对于寻找代码中的错误的答案来说太单调乏味了

以下是我的建议:
我假设您正在运行Linux操作系统
使用-g标志重新编译代码, 并使用gdb进行调试


或者您可以将ulimit-c设置为足够大,然后再次运行代码以获取核心文件,并查看它是如何出错的。

代码有点乱。不清楚您为什么要使其变得比需要的更复杂,但您的错误如下:

ptr->str = (char *)malloc(1);
ptr->str = 0;
我想你的意思是:

*(ptr->str) = 0;
否则,您将创建一个单字节内存泄漏并将字符串设置为NULL,这将在以下情况下失败:

printf("%s\n",strNULL->str);

据我所知,您从不为
调用
变量赋值


变量被初始化为空指针,因此
call->anything
的任何引用都会触发未定义的行为。

问题发生在函数
\u string\u set()

问题1:

您正在取消引用未初始化的指针:

free(call->str);
问题2:

调用
未初始化,您正在尝试将内存分配给
str

call->str = (char *)malloc(call->len+1);
call->len
也未初始化

另外,在
main()
中,您正在调用
compare()
,以调用
\u string\u set()
函数返回的
调用
,但没有将比较函数地址分配给
call->compare

简而言之,您的
\u string\u set()
函数充满了

如果我只是在您的
\u string\u set()
函数中进行更正,它将如下所示:

string *_string_set(string *target){
    int i = 0;

    if (target == NULL)
            return NULL;

    if ((call != NULL) && (call->str != NULL)) {
            free(call->str);
            free(call);
    }

    call = malloc(sizeof(string));
    if (call == NULL)
            return NULL;

    call->len = target->len;
    call->str = malloc(call->len+1);
    if (call->str == NULL) {
            free(call);
            return NULL;
    }

    call->compare = target->compare;
    call->set = target->set;

    for(i = 0;i<call->len;i++){
            call->str[i] = target->str[i];
    }

    return call;
}
string*\u string\u集合(string*目标){
int i=0;
if(target==NULL)
返回NULL;
如果((调用!=NULL)&&(调用->str!=NULL)){
免费(呼叫->str);
免费(电话);
}
call=malloc(sizeof(string));
if(call==NULL)
返回NULL;
调用->len=目标->len;
调用->str=malloc(调用->len+1);
如果(调用->str==NULL){
免费(电话);
返回NULL;
}
调用->比较=目标->比较;
调用->设置=目标->设置;
对于(i=0;ilen;i++){
调用->str[i]=目标->str[i];
}
回电;
}
注意:
\u string\u set()
中的这些更正只是为了修复程序中的分段错误。你的计划还有改进的余地

我可以看到,在您的程序中,您正试图使用
mystr
的值设置
strNULL
。为此,您需要将
strNULL
传递给
\u string\u set()
,并在
\u string\u set()
中进行适当的更改

使用当前实现
\u string\u set()
将使用
mystr
成员变量值设置
调用
成员变量的值,并且
\u string\u set()
返回
调用
mystr
的值不会反映在
strNULL


关于良好编码实践的几点建议:

  • 尽量不要使用globals
  • 永远不要施放
    malloc
    return。检查
  • 在访问指针之前,请确保它指向有效内存
  • 调用
    malloc
    后,始终检查它是否返回了有效内存或NULL
  • 尝试编写模块化代码

  • 它是内置在windows中的XD@Luvid但在类似UNIX的环境中运行?是的,指针中的null字符串导致错误XD,但最后的输出是juse'M'。。发生什么事了?@Lu
    string *_string_set(string *target){
        int i = 0;
    
        if (target == NULL)
                return NULL;
    
        if ((call != NULL) && (call->str != NULL)) {
                free(call->str);
                free(call);
        }
    
        call = malloc(sizeof(string));
        if (call == NULL)
                return NULL;
    
        call->len = target->len;
        call->str = malloc(call->len+1);
        if (call->str == NULL) {
                free(call);
                return NULL;
        }
    
        call->compare = target->compare;
        call->set = target->set;
    
        for(i = 0;i<call->len;i++){
                call->str[i] = target->str[i];
        }
    
        return call;
    }