سؤال

وأنا المسلم مبتدئ الثابت C، ولكن هذا حصل لي متعكز. أنا أعمل على تطبيق قائمة مرتبطة لممارسة، وأنا اتلقى segfault ببساطة عن طريق إضافة متغير إلى وظيفة split_node:

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

struct Node {
    struct Node *child;
    char *content;
};

void print_list(struct Node node);
void split_node(struct Node *node, int position);

int main() {

    struct Node head, second, third;

    head.content = "first";
    second.content = "second";
    third.content = "i'm third";

    head.child = &second;
    second.child = &third;

    print_list(head);
    split_node(&head, 3);
    print_list(head);

    return 0;
}

void print_list(struct Node node) {
    printf("%s\n", node.content);
    if(node.child) print_list(*node.child);
}

    /*
    Split node into two nodes, with the first position characters of the node's content remaining with node, and the remainder being copied to the new node. (It doesn't yet truncate the first node's string, but does do the copy.)
    */
void split_node(struct Node *node, int position) {
    if(position >= strlen((*node).content)) return;
    struct Node newNode;
    newNode.child = (*node).child;
    (*node).child = &newNode;

    int length = (strlen((*node).content) - position);
    newNode.content = malloc(sizeof(char) * (length + 1));
    strncpy(newNode.content, (*node).content + sizeof(char) * position, length);
    newNode.content[length] = '\0';

    //int foo;
}

وهذا الرمز يجمع (دول مجلس التعاون الخليجي سور الصين -o قائمة list.c) ويعمل على ما يرام:

$ ./list
first
second
i'm third
first
st
second
i'm third

ولكن اذا كنت غير تعليق int foo في نهاية split_node، ترجمة وتشغيل، وأحصل على:

$ ./list
first
second
i'm third
first
st
Segmentation fault

وجدب يعطيني هذا المتتبع الخلفي:

#0  0x91d6ae70 in strlen ()
#1  0x91dd3126 in puts ()
#2  0x00001f21 in print_list (node={child = 0xbcec815b, content = 0x8b000000 <Address 0x8b000000 out of bounds>}) at list.c:41
#3  0x00001f3c in print_list (node={child = 0x8fe0154b, content = 0x1ff6 "i'm third"}) at list.c:42
#4  0x00001f3c in print_list (node={child = 0xbffff568, content = 0x1fef "second"}) at list.c:42
#5  0x00001f3c in print_list (node={child = 0xbffff570, content = 0x1fe9 "first"}) at list.c:42
#6  0x00001ee0 in main () at list.c:33

لماذا إضافة تعريف متغير يسبب segfault؟ ويبدو أن تحطيم مؤشر المحتوى من العقدة التي أنشئت حديثا. أنا محتار؛ أي مساعدة؟

هل كانت مفيدة؟

المحلول

وتحتاج إلى تخصيص حيوي بك العقد (باستخدام malloc).

وكما لديك، وأعلن العقدة الجديدة على المكدس. عندما يعود الانقسام وظيفة، تلك العقدة الجديدة لم تعد صالحة الذاكرة.

وإضافة متغير يسبب segfault لأن هذا المتغير يتغير تخطيط مكدس يسبب سلوك مختلف قليلا عندما ترجع الدالة.

نصائح أخرى

وحاول إعداد الخاصية العقد الطفل إلى NULL، C لا الصفر التلقائى من الذاكرة بحيث يبدو مثل الخاص بك قد يكون القمامة في الطفل (أو الخاص يمكن استخدام calloc بدلا من malloc). الجواب المنبر هي أيضا صحيحة.

Valgrind هو أداة عظيمة للمساعدة في العثور على هذه الأنواع من المشاكل. يمكنك القيام بذلك تماما "myappname valgrind" من سطر الأوامر، وسوف تعطيك التفاصيل حول هذه الأنواع من الأخطاء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top