使用指针

时间:2017-11-21 09:03:25

标签: c string pointers segmentation-fault

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

  

Mystr
分段错误(核心转储)

我猜strNULL并设置函数导致错误.. 我猜错了吗?

我不确定是什么问题。 请告诉我有什么问题以及如何解决它。
如果建议我的编码风格,我将不胜感激:D

globalcall.c(声明全局指针)

void *call = 0;

string1.h(标题文件)

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);



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;
}



主文件

#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;
}

4 个答案:

答案 0 :(得分:1)

据我所知,从不call变量分配值。

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

代码有点混乱。目前尚不清楚为什么你要使它变得比它需要的更复杂,但你的段错是在这里:

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

我认为你的意思是:

*(ptr->str) = 0;

否则,您正在创建一个单字节内存泄漏并将字符串设置为NULL,这将失败:

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

答案 3 :(得分:0)

问题出现在函数_string_set()中。

问题没有。 1:

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

free(call->str);

问题没有。 2:

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

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

call->len未初始化

此外,在main()中,您正在为compare()函数返回的call调用_string_set(),但无法将比较函数地址分配给call->compare。< / p>

简而言之,您的_string_set()功能已满undefined behaviors

如果我只是在_string_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_set()中的这些更正只是为了修复程序中的细分错误。您的计划还有改进的余地。

我可以看到,在您的计划中,您尝试将strNULL设置为mystr。为此,您需要将strNULL传递给_string_set()并在_string_set()中进行相应的更改。

使用当前实施_string_set()会将call成员变量的值设置为mystr成员变量值,并_string_set()返回{ {1}}。 call的值不会反映在mystr中。

很少有关于良好编码实践的建议:

  1. 尽量不要使用全局变量。
  2. 永远不要施放strNULL。检查this
  3. 在访问指针之前,请确保它指向有效的内存。
  4. 调用malloc后,请始终检查是否已返回有效内存或NULL。
  5. 尝试编写模块化代码。