что не так с этим кодом .. относительно strncat - PullRequest
1 голос
/ 01 июня 2011

извините, я изменил код сейчас:

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

void main()
{
    int i=0;
    char** f=NULL;
    char* ff=NULL;

    ff="abcd";

    f=( char**)malloc ((i + 1) * sizeof (char *)+5);
    f[0]=ff;
 // strcpy(f[0],ff); (this again giving same error)
    strncat(f[0],"efg",3);
    printf("f : %s",f[0]);
}

Я получаю необработанное исключение, ошибка записи нарушения прав доступаМожет кто-нибудь объяснить мне ошибку, которую я сделал здесь.ПРИМЕЧАНИЕ: извините, я изменил код сейчас:

Спасибо за ответы

Ответы [ 7 ]

5 голосов
/ 01 июня 2011

Второе назначение f фактически удаляет первое назначение.Чтобы скопировать оригинальную строку, вы должны использовать strcpy.Кроме того, обратите внимание, чтобы зарезервировать достаточно места в malloc.Это должны быть первые четыре символа "abcd" плюс еще три добавленных "efg" плюс один (окончание \0):

f = (char*)malloc(9); // 5+3+1
strcpy(f, ff);
strncat(f, "efg", 3);
5 голосов
/ 01 июня 2011

вы устанавливаете f
ff указывает на начало константы char [] ("abcd") и затем вы изменяете значение * f (которое в точности равно * ff), таким образом - нарушение доступа.

3 голосов
/ 01 июня 2011

Вы назначаете f для ff. Итак, вы пытаетесь объединить константную строку. Короче говоря, когда вы думаете, что делаете конкатенацию в неправильной области.

strncat(f,"efg",3);

Вы на самом деле делаете это.

strncat(ff,"efg",3);



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *concat(const char *a, const char *b) {
   size_t la = strlen(a);
   size_t lb = strlen(b);
   char *ret= (char*) malloc( la + lb + 1 /* for \0 */);
   memcpy(ret,a,la);
   memcpy(ret+la,b,lb);
   ret[la+lb] = '\0';
   return ret;
}

void main()
{
    char* f=NULL;

    char *f =concat("abcd","efg");

    printf("f : %s",f[0]);
    free(f);
}
1 голос
/ 01 июня 2011
char* ff="abcd"; 
  • "abcd" является const char*, а не char*
f=( char*)malloc ((i + 1) * sizeof (char *)+5);
  • i равно 0, вы имеете в виду strlen(ff)+1
  • char * вместо char
  • 5 просто запутано?
f=ff;
  • f устанавливается на то же значение указателя , что и ff, то есть f указывает на ту же самую константную строку "abcd"
  • утечка памяти, поскольку вы не освободили f=malloc first
strncat(f,"efg",3);
  • 3 слишком мало, он должен включать в себя трейлинг \0 - используйте напо крайней мере 4, чтобы скопировать все "efg"
  • . На самом деле это должен быть размер места назначения - размер, который вы использовали в malloc выше (или, точнее, минимальный размер источника и места назначения).
printf("f : %s",f);
  • отсутствует трейлинг \n (перевод строки)
1 голос
/ 01 июня 2011

ооочень много вещей:

Во-первых, это строковый литерал, должен быть const

char* ff="abcd"; // should not do this

const char* ff = "abcd"; // instead

Следующее ваше malloc - Argh

f=( char*)malloc ((i + 1) * sizeof (char *)+5);

Вам нужно выделить 5 символов (i + 1 == 1), вы также получаете sizeof указатель (char*) вместо char

f=( char*)malloc (5 * sizeof (char));

следующее:

f=ff;

фактически вы перезаписали предыдущее распределение, и теперь f указывает на ff, поэтому strncat терпит неудачу! Однако, даже если вы этого не сделали, strncat завершится неудачно, потому что f, который вы malloc d не будет содержать завершенной строкой NUL, и у вас будут носовые демоны везде.

Итак, удалите указанное выше назначение и memset вновь выделенный блок для 0, и ваш код может просто работать. Если вы используете C ++, то, что вы делаете, эквивалентно

std::string f("abcd");
f.append("efg");

РЕДАКТИРОВАТЬ: я удалил это, чтобы указать на ошибки в вашем коде, а не просто почему он терпит неудачу ...

1 голос
/ 01 июня 2011

Вы пытаетесь объединить в ff, который не доступен для записи.Вот почему вы получаете Access Violation.

Вы устанавливаете f = ff, который указывает указатель f на ff.Это также приводит к утечке памяти.

ff объявлено в сегменте кода, который недоступен для записи, и запись в него вызывает неопределенное поведениеТакое неопределенное поведение в вашем случае является ошибкой нарушения прав доступа.

0 голосов
/ 02 июня 2011
char *ff;
ff = "whatever";

ff назначается строковый литерал, который нельзя изменить.Этот фрагмент строки хранится в области .rodata исполняемого файла в linux и аналогичной области только для чтения в других типах исполняемых файлов.Таким образом, после присвоения строкового литерала ff = "whatever" ff содержит адрес в памяти, который является только для чтения .Делая: char f[0] = ff и затем пытаясь изменить строку f[0], которая фактически указывает на ff, которая снова указывает на базовый адрес строки whatever\0, хранящейся в памяти, которая доступна только для чтения, которую вы пытаетесь изменить, что ОС мешает вам делать.

Либо Вы делаете:

  char *ff;
  ff = malloc (sizeof (char) * SIZE_OF_YOUR_CHOICE);
  strcpy (ff, "whatever");
  /* now do what ever modification (within the size limits) */
  free (ff);

Или вы делаете:

char ff[SIZE_OF_YOUR_CHOICE] = "whatever";
/* not do whatever modification (within the size limits) */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...