c strcat с указателями - PullRequest
       3

c strcat с указателями

2 голосов
/ 27 ноября 2010

Я хочу закодировать этот пример функции на C (пожалуйста, не судите цель этого куска кода, это только для изучения C).Он должен использовать динамическое распределение памяти, чтобы не использовать больше памяти, чем необходимо.

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

char ** LCS ( char * s1, char * s2 ) {
    int i, ii, myI;
    char ** commonSequence = (char**) malloc(1 * sizeof (char**));
    *commonSequence = NULL;

    int commonChars = 0;
    for (i = 0; i < (int)strlen(s1);i++) {
        for (ii = 0; ii < (int)strlen(s2); ii++) {
            if (s1[i] == s2[ii]) {
                commonChars++;
                if (commonChars > 1) {
                    commonSequence = (char**) realloc(commonSequence, (commonChars+1) * sizeof (char**));
                    strcat((char*)commonSequence, (const char *)s1[i]);
                }
                i++;
            }
        }
    }

    return commonSequence;
}

int main ( int argc, char * argv [] ) {
    char ** output = LCS((char*)"AATK", (char*)"AABC");

    printf("\n\nCommon: %s", *output);
    free(output);

    return 0;
}

Приведенный выше код вызывает ошибку «Ошибка сегментации» (возможно, что-то не так с распределением памяти или чем-то подобным).Когда я запускаю его в Valgrind, он выводит следующее:

==29381== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 3 from 3)
==29381==
==29381== 1 errors in context 1 of 1:
==29381== Invalid read of size 1
==29381==    at 0x4028A80: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-l                                                                                          inux.so)
==29381==    by 0x80485BA: LCS(char*, char*) (main.cpp:19)
==29381==    by 0x8048626: main (main.cpp:31)
==29381==  Address 0x41 is not stack'd, malloc'd or (recently) free'd

Возможно, я неправильно использую функцию strcat ... Но я на самом деле не знаю, что исправить...

Ответы [ 5 ]

2 голосов
/ 28 ноября 2010

Вы используете malloc фиктивно, но, поскольку числа работают правильно, ошибка, скорее всего, не будет обнаружена.Эта строка:

char ** commonSequence = (char**) malloc(1 * sizeof (char**));

должна выглядеть следующим образом:

char ** commonSequence = malloc(1 * sizeof (char*));

или предпочтительно:

char ** commonSequence = malloc(1 * sizeof *commonSequence);

Окончательная форма является самой хорошей, поскольку она не требует каких-либо изменений, есливы меняете тип commonSequence.Что касается фактической проблемы с исходной строкой, вам нужно выделить ее в зависимости от размера объекта, на который вы будете указывать, а не от размера указателя, который на него указывает.На практике, поскольку оба указателя являются одинаковыми по размеру на современных машинах реального мира, но это все еще серьезная концептуальная ошибка, которая может укусить вас, когда вы применяете неправильный шаблон к типам без указателей.Например, это может привести к повреждению памяти / неопределенному поведению:

struct foobar *foo = malloc(1 * sizeof (struct foobar *));

, поскольку вместо размера структуры будет выделяться только 4 или 8 байтов.

2 голосов
/ 27 ноября 2010

Вы переводите s1[i], который является char, в бессмысленный указатель const char *:

strcat((char*)commonSequence, (const char *)s1[i]);

Вы также конвертируете commonSequence из char ** вchar *, что не сработает.Вы, вероятно, хотите что-то вроде:

strcat(*commonSequence, ((const char *)s1)[i]);

Но в том, как вы выделяете память для commonSequence, действительно что-то не так.Похоже, вы строите список строк без выделения самих строк.

0 голосов
/ 28 ноября 2010

Вам нужно передать адрес s1 [i]. Просто приведение не сделает его действительным адресом. В равной степени приведение char ** к char * не даст ожидаемого результата. Вы должны разыменовать его для доступа к указателю char *, хранящемуся в char **

strcat( *commonSequence, &s1[i] );

Тем не менее, остальная часть кода выглядит подозрительно. Интересно, что вы на самом деле пытаетесь достичь? Но вы прямо просили нас не сомневаться в этом!

0 голосов
/ 28 ноября 2010

Вы выделяете память для указателя на указатель на строку, но не для самой строки. Первый аргумент strcat() выглядит так: *commonSequence.

0 голосов
/ 27 ноября 2010
 strcat((char*)commonSequence, (const char *)s1[i]);

strcat нужен указатель, то, что вы делаете с (const char *)s1[i], это то, что вы получаете доступ к символу и затем передаете его как указатель.То есть вместо адреса, с которого должен начинаться strcat, вы указываете ему значение символа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...