简体   繁体   English

是什么导致此段错误?

[英]What is causing this segfault?

[This question has been edited heavily since yesterday. [自昨天以来,对该问题进行了大量编辑。 I'm updating to clarify the question.] 我正在更新以澄清问题。]

I get a segfault after calling mygets(). 调用mygets()后出现段错误。 Here is my code: 这是我的代码:

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

    typedef struct _charlist{
        char ch;
        struct _charlist *next;
    }charlist;

    static struct termios old, new;
    void mygets(char** p);
    char getche(void); 
    char getch_(int echo);
    void resetTermios(void);
    void initTermios(int echo);


    int main(void){
        char *p;

        printf("\nWho loves orange soda?: ");
        mygets(&p);
        printf("'%s' loves orange soda!", p);
    }


    void mygets(char** p){
        char c;
        charlist *root, *curr;
        unsigned i, count=0;

        root=NULL;

    while((c = getche()) != '\n'){      

        count++;    
        if(!root){ 
            root = (charlist*) malloc(sizeof(charlist));
            root->ch = c;
                root->next = NULL;
                curr = root;
            }

            else{
                curr
->next = (charlist*) malloc(sizeof(charlist));
                curr->next->ch = c;
                curr->next->next = NULL;
                curr = curr->next;
            }
        }

        //now request string space.
        *p = (char*) malloc((count+1)*sizeof(char));

        printf("\np is now malloced");      //This line doesn't get printed!

        //move linked list into string space.
        curr = root;
        for(i=0; i<=count; i++){
            *p[i] = curr->ch;
            curr = curr->next;
        }

        //null-terminate the string.
        *p[i] = '\0';

    }

Can someone tell me why I get a segfault? 有人可以告诉我为什么会出现段错误吗?

I can't post this question unless the ratio of code to question is lower than some arbitrary threshold. 除非代码与问题的比率低于某个任意阈值,否则我无法发布此问题。 Therefore, there now follows the first paragraph of Alice in Wonderland, for your consideration. 因此,下面是《爱丽丝梦游仙境》的第一段,供您考虑。

Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice 'without pictures or conversation?' 爱丽丝开始不厌其烦地坐在姐姐在银行旁,无事可做:她曾一两次偷窥妹妹正在读的书,但里面没有照片或谈话,“还有什么?是用书吗?”爱丽丝想,“没有照片或谈话?”

When func is called, it is passed a copy of the local variable p in main . 调用func ,将在main传递局部变量p副本 This copy is then assigned the malloc ed area in func . 然后,此副本分配malloc在编辑区func The original p in the main is never modified, so its contents remain undefined, causing a segmentation fault when printf dereferences p in order to print the string. main的原始p从未修改,因此其内容保持未定义状态,当printf引用p以便打印字符串时,会导致分段错误。

You may want func to return a char* pointing to the newly malloc'd area. 您可能希望func返回指向新分配的区域的char*

You pass the argument to the function by value. 您通过值将参数传递给函数。 So according to the function declaration 所以根据功能声明

void func(char* p);

parameter p is a local variable of the function that will be destroyed after exiting the function. 参数p是函数的局部变量,在退出函数后将被销毁。 Any changes of the local variable do not influence on the argument. 局部变量的任何更改都不会影响参数。

You could define the function the following ways 您可以通过以下方式定义函数

char * func(){
    unsigned count = 10;
    char *p = (char*) malloc(sizeof(char)*(count+1));

    //p is given a string after this, but problem is the above line.

   return p;
}

and call it as 并称其为

p = funct();

or 要么

void func(char ** p){
    unsigned count = 10;
    *p = (char*) malloc(sizeof(char)*(count+1));

    //p is given a string after this, but problem is the above line.
}

and call it as 并称其为

func( &p );

The problem is with: 问题在于:

*p[i] = curr->ch;

Should be: 应该:

(*p)[i] = curr->ch;

You want to access the i 'th character of where p is pointing to. 您想访问p指向的第i个字符。 Not dereference the i th pointer in an array of pointers. 不取消引用指针数组中的第i个指针。

Same problem with *p[i] = '\\0'; *p[i] = '\\0';同样的问题*p[i] = '\\0'; later. 后来。

Also you did not malloc enough space, as your loop writes count + 1 characters and then you write an extra null terminator, so you should either malloc count + 2 or adjust your loop to finish at i<count , not i<=count . 另外,您没有分配足够的空间,因为您的循环写入了count + 1字符,然后又编写了一个额外的空终止符,因此您应该malloc count + 2或调整循环以在i<count而不是i<=count (probably the latter). (可能是后者)。

Also, it'd be useful to check curr != NULL before dereferencing it, so that if you do have an off-by-one error then you don't get undefined behaviour. 另外,在取消引用前检查curr != NULL很有用,这样,如果您确实有一个错误的错误,那么您就不会得到不确定的行为。

Disclaimer : at the time of this answer, the question didn't even include the real cause of the problem , and had few enough code that both these suggestions were the only thing that could have gone wrong. 免责声明 :在回答此问题时, 问题甚至没有包括问题的真正原因 ,并且代码不足,因此这两个建议都是唯一可能出错的问题。 Now that OP posted his actual code at some time during the night , it is invalidated. 现在,OP在夜间某个时间发布了他的实际代码,该代码已失效。 Please don't downvote it based on this, for obvious reasons. 出于明显的原因,请不要基于此投票。

- --

Remove that (char*) cast. 删除(char*)演员表。 You'll most certainly get an "assignment makes pointer from integer without a cast" warning. 您肯定会收到“赋值使整数不带强制转换的指针”警告。

Then #include <stdlib.h> so you can actually use malloc & co without causing Undefined Behaviour from a mismatched function signature. 然后#include <stdlib.h>因此您实际上可以使用malloc &co,而不会因不匹配的函数签名而导致未定义行为。

Edit: There will be a similar problem if you didn't declare func before calling it in main . 编辑:如果在main调用func之前没有声明func ,也会出现类似的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM