Int 指针不为空,可以打印,但不能在不引发分段错误的情况下传递给函数

Posted

技术标签:

【中文标题】Int 指针不为空,可以打印,但不能在不引发分段错误的情况下传递给函数【英文标题】:Int pointer is not null and can be printed but can not be passed into a function without throwing a segmentation fault 【发布时间】:2018-01-26 02:04:58 【问题描述】:

我正在为一个 int 指针分配一个从 sscanf 提取的值。然后我想将它传递给来自不同文件counters_add 的方法。虽然我可以打印出存储在指针中的值及其地址,但只要我将它传递给这个方法,程序就会抛出一个段错误。从测试中我知道程序在段错误之前甚至没有进入这个方法。

这个方法接受(counters_t *ctrs, const int key)的参数。 counters_t 对象是我在文件前面定义的结构。

我不会过早地释放任何东西,并且已经验证ctrskey 都不是NULL。为什么会出现分段错误?

int *key = malloc(sizeof(int));
//check if key is null here
sscanf(line, "%i", key);
printf("key: %i\n", *key); //this prints out the value
printf("key: %p\n", (void *)key); //this prints out the address
counters_add(ctrs, *key);//seg fault here, without even getting inside of method

ctrs的初始化:

counters_t *ctrs = count_malloc(sizeof(counters_t));
if (ctrs == NULL) 
    return NULL; // error allocating set
 else 
    // initialize contents of set structure
    ctrs->head = NULL;

其余代码:

void
counters_add(counters_t *ctrs, const int key)

    if (key >= 0 && ctrs != NULL) 
        // allocate a new node to be added to the list if the key is not already      in the set
        if(counters_get(ctrs,key) == 0) //if it doesnt already exist
            printf("after first if statement");
            counternode_t *new = counternode_new(&key);//create it
            printf("aftermaking new node");
            new->next = ctrs->head;//add it to the head of the list
            ctrs->head = new;
         else 
            // increment the count
            for(counternode_t *curr = ctrs->head; curr != NULL; curr = curr->next)
                if (*(curr->key) == key)
                    *(curr->count) = *(curr->count) + 1;
                
            

        
    


int
counters_get(counters_t *ctrs, const int key)

    printf("in counters_get");
    if (ctrs == NULL) 
        return 0; // null counter
     else if (ctrs->head == NULL) 
        return 0; // set is empty
    //remove this in set
    else 
        for(counternode_t *curr = ctrs->head; curr != NULL; curr = curr->next)
        
            if (*(curr->key) == key)
                    return *(curr->count);
            printf("in loop");
        
        return 0;
    


static counternode_t  // not visible outside this file
*counternode_new(const int *key)

    counternode_t *node = count_malloc(sizeof(counternode_t));
    int *newkey = (int*)malloc(sizeof(int));
    newkey = (int*) memcpy(newkey, key, (50  * sizeof(char)));
    //make sure key is not over 50 ints 
    if (node == NULL || newkey == NULL) 
        // error allocating memory for node or new key; return error
        return NULL;
     else 
        node->key = newkey;
        *(node->count) = 1;
        node->next = NULL;
        return node;
    

这是计数器结构:

typedef struct counters 
    struct counternode *head;           // head of the list of items in set
 counters_t;

这里是countersnode:

typedef struct counternode 
    int *key;
    int *count; //pointer to counter for this node
    struct counternode *next;           // link to next node
 counternode_t;

【问题讨论】:

问题很可能在于ctrs。你是怎么声明ctrs的?你初始化了吗? 请创建一个minimal reproducible example。 counters_add 有原型吗? "我在之前的代码中声明了ctrs,并为其声明了malloc内存。我还检查它是否为null。" -- 不要告诉我们,给我们看。我们应该能够从问题中复制并粘贴您的代码并自己运行以重现问题。 不要只是添加多个不连贯的代码块。从显示问题的程序开始,尽可能缩小范围,使其仍然显示相同的问题。您应该能够将其缩短到 20 行左右。然后将该完整的程序作为单个代码块发布。正如我所说,我们应该能够复制并粘贴您的整个程序并自己重现问题。我不愿意复制和粘贴当前问题中的 7 块代码中的每一个,并弄清楚如何将它们重新组合在一起。 【参考方案1】:

我在counternode_new看到了问题:

static counternode_t  // not visible outside this file
*counternode_new(const int *key)

    counternode_t *node = count_malloc(sizeof(counternode_t));
    int *newkey = (int*)malloc(sizeof(int));
    newkey = (int*) memcpy(newkey, key, (50  * sizeof(char)));
    ...

counters_add 中,您将一个指向变量d 的指针传递给counternode_new。 然后在counternode_new 中,你想用key 复制newkey 50 个字节为 来源。但是key 是指向 single 整数的指针,所以你读的是 49 字节超出范围,这会导致未定义的行为,这可能会导致 段错误。此外,您仅为newkey 的单个int 分配空间。此外,您正在复制 50 个字节,而不是 50 个整数。我不明白 50 是从哪里来的。

所以你的counternode_new 调用counters_add 没有意义,首先你必须 为int[50] 数组分配空间并将其传递给counternode_new

【讨论】:

这似乎是正确的,这是一个很大的错误,所以我取出了 50,只剩下一个 int 的空间。但是,这并不能解释为什么 counters_add 根本没有被调用。 @grassss 我不知道,应该是,至少从您发布的代码部分来看。请阅读minimal reproducible example。【参考方案2】:

我注意到newkey 只分配了sizeof(int),而您似乎将 50 个字节复制到 newkey。

int *newkey = (int*)malloc(sizeof(int));
newkey = (int*) memcpy(newkey, key, (50  * sizeof(char)));

【讨论】:

以上是关于Int 指针不为空,可以打印,但不能在不引发分段错误的情况下传递给函数的主要内容,如果未能解决你的问题,请参考以下文章

打印指针时出现分段错误

spring bean注入报空指针null,但set设值时对象是存在的,而且只是部分方法报空指针

MySQL - 仅在不为空时连接

在指针c ++的向量中打印指针的值[重复]

在java中为啥做了非空判断,但还是报错,比如下面,都做了是不是为null的判断,但是运行到那还是报null错

仅在不为空时比较字段