strncmp/strcpy источник повреждения

сегодня я пытался подружиться с char * string... но, кажется, у меня не получается :) Каждый раз, когда я вызываю функцию strcmp/strncmp/strcpy, мой источник повреждается...

вот фрагмент

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

struct student
{
    int UID;
    char name[20];
    char surname[20];
};

char * getString(int minChars, int maxChars);

struct student * myStud;

int main(int argc, char** argv) {

    myStud = (struct student*)malloc(sizeof(struct student));
    while(1)
    {
        printf("\nEnter new name: ");
        strcpy(myStud->name,getString(1,19));
        printf("\n The values is now %s",myStud->name);
    }
    return (EXIT_SUCCESS);
}

char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];
scanAgain:
    scanf("%s",&string);
    if(strlen(string)<minChars)
    {
        printf("\nToo few symbols, try again: ");
        goto scanAgain;
    }
    if(strlen(string)>maxChars)
    {
        printf("\nToo many symbols, try again: ");
        goto scanAgain;
    }
    string[maxChars]='\0';
    return(string);
}

Выход:

Enter new name: Alekasdasd

 The values is now Alekasda�#
Enter new name: 

Я всего лишь новичок, так что это может быть что-то очень простое... может быть и нет. да, кстати, используя Linux и NetBeans в качестве SDK, gcc в качестве компилятора.


person Alex    schedule 12.03.2011    source источник
comment
Напишите небольшую программу, воспроизводящую проблему. (Кроме того, рассмотрите возможность реструктуризации вашей программы, чтобы в ней не было путаницы с метками и переходами...)   -  person James McNellis    schedule 13.03.2011
comment
УРА! Источник поврежден! Надеюсь, вы не имели в виду исходник программы :)   -  person pmg    schedule 13.03.2011
comment
Начните с включения предупреждений на вашем компиляторе. Это должно дать вам несколько вещей, чтобы пересмотреть.   -  person Mike Sherrill 'Cat Recall'    schedule 13.03.2011


Ответы (4)


char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];
    ...
    return(string);
}

Массив «string» здесь выделен только для области действия функции getString(). Как только он возвращается (выходит за пределы области видимости), он перестает существовать и будет перезаписан остальной частью вашей программы. Оператор return(string) возвращает указатель этих данных, которые больше не выделены, а не сами данные. Это происходит из-за неявного преобразования массива в указатель в C.

Вместо этого ваша функция getString() должна принимать char* в качестве аргумента, который выделяется в вызывающей функции.

person intgr    schedule 12.03.2011
comment
спасибо, я только что написал эту штуку для получения строки, потому что меня раздражают ошибки сегментации при использовании scanf(), а также автоматическое чтение scanf сразу после printf()... - person Alex; 13.03.2011

Вы возвращаете указатель на переменную стека.

char * getString(int minChars, int maxChars)
{

    char string[maxChars+1];

Когда getString возвращается, string недействителен. Ваше возвращаемое значение указывает на эту недопустимую строку.

Использовать:

char * getString(int minChars, int maxChars, char * string) {

    return string;
}
...
char string[100];
getString(1, 2, string);

Кроме того, goto? Прекратите, пожалуйста, используйте for, while do, do while, но не goto

person Erik    schedule 12.03.2011
comment
да, я знаю о гото, плохо это изменю :)) - person Alex; 13.03.2011
comment
У Эрика есть отличное замечание о способе не полагаться на скрытый буфер, который может привести к дефектам в коде. - person Heath Hunnicutt; 13.03.2011
comment
Не верьте слепо, что goto – это плохо, поймите, почему это так. Это плохо только потому, что может привести к менее читаемому коду. Есть (очень ограниченные) ситуации, когда его можно использовать (не этот конкретный случай, поскольку вы можете достичь того же результата с помощью более структурированных циклов). - person paxdiablo; 13.03.2011

Я вижу две проблемы с вашей функцией getString():

  1. Строковая переменная должна быть объявлена ​​static, чтобы используемая для нее память не освобождалась (стекалась, извлекалась) при выходе из функции.
  2. Параметром для scanf() вам не нужен токен &, а просто указатель на буфер, string.

То есть меняем строки:

char string[maxChars+1];
scanf("%s",&string);

читать

static char string[maxChars+1];
scanf("%s",string);

Причина, по которой вам не нужен амперсанд в вызове scanf(), приведена на странице руководства man 3 scanf:

      s      Matches a  sequence  of  non-white-space  characters;  the  next
              pointer must be a **pointer to character array** that is long enough
              to hold the input sequence and the  terminating  null  character
              ('\0'), which is added automatically.  The input string stops at
              white space or at the  maximum  field  width,  whichever  occurs
              first.
person Heath Hunnicutt    schedule 12.03.2011
comment
static не очень хорошее решение - он создает такие проблемы, которые трудно найти, когда он, например. звонит foo(getString(), getString()) - person Erik; 13.03.2011
comment
Звонки производят только программисты. Поэтому очень важно, чтобы программисты на C понимали static. ОП пишет, что учится сегодня. Я пришел к выводу, что ему лучше поэкспериментировать со статикой, а также исправить использование указателя и учиться, чем беспокоиться о проблеме, которой у него сейчас нет. Забавно, что слово «статика» используется для обозначения стазиса, а стало означать искрящийся шум. Не столкнется ли он когда-нибудь с описанной вами проблемой? Что произойдет в тот день? - person Heath Hunnicutt; 13.03.2011
comment
статика полезна. Но ИМО это неправильно для этой функции. Кроме того, &string и string эквивалентны в этом контексте, хотя использование только string делает исходный код более красивым. - person Erik; 13.03.2011

240 строк - это не "фрагмент". Как предложил Джеймс в своем комментарии, сократите код до минимального количества строк, необходимого для воспроизведения проблемы. На этом этапе причина проблемы должна стать для вас очевидной, если нет, попробуйте опубликовать еще раз.

person 2.718    schedule 12.03.2011
comment
0:-1 за отсутствие ответа; +1 за очень хорошее предложение. Итого получается 0 :) - person pmg; 13.03.2011