2013-04-03 3 views
2

Для жизни моего я не могу понять, почему эта программа не работает. Я пытаюсь соединить две строки с помощью указателей и продолжать получать эту ошибку:Добавление строк с помощью указателей В C

a.out(28095) malloc: *** error 
for object 0x101d36e9c: pointer being realloc'd was not allocated 
*** set a breakpoint in malloc_error_break to debug 

Мой str_append.c:

#include <stdio.h> 
#include <stdlib.h> 
#include "stringlibrary.h" /* Include the header (not strictly necessary here) */ 

//appends s to d 
void str_append(char *d, char *s){ 
    int i=0, j=0; 

    d = realloc(d, strlength(d)+strlength(s)+1); 
    //find the end of d 
    while(*(d+i)!='\0'){ 
    i++; 
    } 


    //append s to d 
    while(*(s+j)!='\0'){ 
    *(d+i)=*(s+j); 
    i++; 
    j++; 
    } 
    *(d+i)='\0'; 


} 

У меня есть своя функция strlength который я 100% уверен, что работает.

Мой main.c:

#include <stdio.h> 
#include <stdlib.h> 
#include "stringlibrary.h" 

int main(int argc, char **argv) 
{ 
char* str = (char*)malloc(1000*sizeof(char)); 
str = "Hello"; 
char* str2 = (char*)malloc(1000*sizeof(char)); 
str2 = " World"; 

str_append(str, str2); 


printf("Original String: %d\n", strlength(str)); 
printf("Appended String: %d\n", strlength(str)); 


return 0; 
} 

Я пытался перераспределить во временную переменную и получить ту же ошибку. Любая помощь приветствуется.

EDIT: Спасибо за все ответы. Этот сайт потрясающий. Я не только знаю, где я поступил не так (простая ошибка, я думаю), но я нашел довольно большое отверстие в том, что я не знал о струнах. Поскольку я не могу использовать функцию strcpy, я реализовал свою собственную. Это исходный код для strcpy.

char *string_copy(char *dest, const char *src) 
{ 
char *result = dest; 
while (*dest++ = *src++); 
return result; 
} 

ответ

5

Ваша проблема здесь

char* str = (char*)malloc(1000*sizeof(char)); 
str = "Hello"; 

Прежде всего выделить место для 1000 символов и наведите указатель на начало этой памяти.
Затем во второй строке вы указываете указатель на строковый литерал, вызывающий утечку памяти.
Указатель больше не указывает на выделенную память.
И позже в вашей функции вы пытаетесь изменить строковый литерал, который доступен только для чтения.

+0

После таНос-ки памяти для указателя на строку, чтобы присвоить ему некоторые данные, которые вы можете захотеть сделать что-то например strcpy (str, «Hello»); – TheCodeArtist

+0

@ TheCodeArtist и Армин Спасибо! Ничего себе, мои умения C не в курсе, я думаю. Как я могу назначить строку выделенной памяти без использования strcpy? Это назначение, и мне не разрешено использовать библиотеку string.h. – Raz

+0

Могу ли я создать новый указатель, указывающий на начало строкового литерала, а затем зациклировать новый указатель на выделенную память для указателя str? – Raz

4

Вы пытаетесь перераспределить указатель на статическую переменную. При установке

str = "Hello";

Вы статически присваивая этой переменной (т.е. он будет назначен во время компиляции). Это не действительный указатель для использования в других целях, включая realloc. Вы также тратите все пространство, которое вы получили с помощью malloc, на линии выше, отбросив только ваш указатель на эту память.

Что вам нужно сделать, вместо того, чтобы использовать strcpy присвоить значение:

strcpy(str, "Hello");

Тогда вы еще динамически выделяемый указатель, который можно использовать для realloc.

+0

Спасибо. Я ошибочно думал, что назначаю строковый литерал в выделенную память. Я обвиняю свой единственный опыт в Java-кодировании и ограниченных знаниях с C. :) – Raz

2
char* str = (char*)malloc(1000*sizeof(char)); 
str = "Hello"; 

должно быть:

char* str = malloc (1000); 
strcpy (str, "Hello"); 

Прежние выделяет часть памяти и хранит адрес этой памяти в str указатель, то изменяетstr указатель, чтобы указать на разные (unmalloced) Память.

Именно поэтому вы видите pointer being realloc'd was not allocated.

Последний сегмент кода оставляет str, указывая на память malloced и просто копирует строку в эту память.


И, как в сторону, вы никогда не должны отбрасывать возвращаемое значение из malloc в C - это может скрыть некоторые тонкие ошибки, и это ненужно, так как C вполне может неявно отливку void* возвращается в любой другой тип указателя ,

Кроме того, поскольку sizeof(char) всегда один, вам никогда не нужно его умножать. Он обычно загромождает код без необходимости.

Наконец, хотя, вероятно, не так уж важно в данном случае, стандартный C резервирует идентификаторы, начинающиеся с str, mem и wcs (каждый с последующим строчной буквой) для будущих направлений библиотеки, так что вы можете захотеть пересмотреть ваше использование вещей подобный strlength() если хотите будущее портативность.

+0

Спасибо. Мне нужно многому научиться, и вы действительно помогаете расширить некоторые вещи, которые я еще не совсем понял. Я бы использовал цикл, который указывал на начало строкового литерала, чтобы скопировать его в разделяемую память? – Raz

+0

@ user2066723, я бы просто использовал 'strcpy' сам, но если вы не можете использовать эту функцию (например, домашнее задание), вы будете цитировать символ по символу, как и в' str_append'. – paxdiablo

1

строки литералы (например: "MAMA" "MEME") являются неизменяемыми. вы не можете перераспределить их, однако, если вы используете указатель символов (например, char * s = (char*)malloc(sizeof(char) * LEN) и выделяете их, то они изменяемы.

здесь:

char* str = (char*)malloc(1000*sizeof(char)); 
str = "Hello"; //no error BUT wasted memory and cant be reallocated anymore (literal) 

вы должны использовать встроенные функции работы со строками ...

Смежные вопросы