2012-02-01 4 views
1

Я пытался реализовать простую функцию, которая может конкатенировать любое количество переданных ей строк. Мой вызов realloc завершился неудачно. Это связано с тем фактом, что строковые аргументы, которые я передаю функции, хранятся в сегменте данных, где, когда realloc пытается выделить память из кучи? Это просто идея, которую я имею. Я новичок, поэтому, пожалуйста, извините, если это кажется глупым. Как я могу запустить эту функцию?realloc() Failure

//Program to implement a function that can concatenate any number of argumnets 

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

char *mstrcat(char *first, ...); 
int main(int argc, int **argv){ 
    char *s; 
    s=mstrcat("I ","Love ","Stack","Overflow"); 
    printf("%s\n",s); 
} 
char *mstrcat(char *first, ...){ 
     char *s=first,*p; 
     int len=0; // stores the length of the string as it grows 
     len=strlen(s); 
     va_list aptr; // creates a pointer to the unnamed argument list 
     va_start(aptr,first); // initialise aptr to the first unnamed argument 
     if(aptr==NULL){ 
     return s; 
     } 
     while((p=va_arg(aptr,char *))!=NULL){ // till there are no more arguments to process 
     len+=strlen(p); 
     if((s=(char *)realloc(s,len+1))!=NULL){ 
      strcat(s,p); 
     } 
     else{ 
      printf("Failed to concatenate\n");  
      return first; 
     } 
     } 
     return s; 
} 
+1

Вы не передаете NULL в качестве последнего аргумента для mstrcat здесь. Это заставит ваш цикл читать данные мусора. Это действительно тестовый пример, который вы используете? Если нет, можем ли мы увидеть реальный тестовый пример? – templatetypedef

+1

Были ли строки, которые вы передаете mstrcat(), выделенные malloc() или компанией? В противном случае вы не можете сделать realloc() на них. Как указано [здесь] (http://linux.die.net/man/3/realloc): * Если значение ptr равно NULL, оно должно быть возвращено предыдущим вызовом malloc(), calloc() или realloc() . * – m0skit0

+0

@templatetypedef я добавил 'NULL' и следующие строки кода, и он работал нормально. 'len = strlen (first);' s = (char *) malloc (len + 1); '' strcpy (s, first); '. Спасибо за вашу помощь. – Bazooka

ответ

2

Ваш код имеет Неопределенное поведение. Стандарт указывает, что указатель, передаваемый на realloc, должен точно соответствовать указателю, которому была назначена динамическая память, используя функцию управления памятью. Функции управления памятью, указанные стандартом, следующие:
aligned_alloc, calloc, malloc и realloc.

Указатель, который вы передаете realloc(), не был возвращен ни одним из них и, следовательно, неопределенным поведением.

Ссылка:
c99 стандарт: 7.22.3.5 Функция перераспределить

Синопсис: # 1

#include <stdlib.h> 
void *realloc(void *ptr, size_t size); 

# 3

Если PTR является нулевым указателем , функция realloc ведет себя как функция malloc для указанный размер. В противном случае , если ptr не соответствует указателю, ранее возвращенному функцией управления памятью , или если пространство было освобождено вызовом свободной или функции realloc, поведение не определено. Если память для нового объекта не может быть выделена , старый объект не освобождается и его значение не изменяется.

0

Точка о realloc, то size аргументе нового размера выделенных данных, которые для вас должны быть старая длиной s плюс длиной p (+1 за терминатор, конечно).

И как вы подозреваете, вы не можете использовать строку first в качестве основы перераспределения. Вместо этого установите s в NULL в начале функции.

+0

Я верю, что сделал это на этапе 'len + = strlen (p)'. – Bazooka

+0

@Parminder Ах, извините, не видел этого вначале. –

0

Вы передаете строковые литералы в свою mstrcat функцию, и они, вероятно, хранятся в области только для чтения процесса, что означает, что они не могут быть изменены или изменены.

realloc может использоваться только с указателем, ранее возвращенным malloc или realloc. Другие виды использования (как и ваши) дают неопределенное поведение.

0

Функция mstrcat начинается с указания s на первый аргумент. Затем вы пытаетесь перевернуть() этот указатель, который является статической строкой. Это не будет работать. Вы можете перераспределить указатель, ранее выделенный malloc().

Предлагаю вам изменить char *s=first на char *s=strdup(first), чтобы выделить копию первого аргумента, а затем этот код должен работать.

Алгоритм конкатенации довольно неэффективен, но это еще одна история ... (подсказка: вы можете перечислить аргументы и отслеживать общий размер, затем выделить() соответствующий буфер и затем объединить все аргументы в it)

+0

Я согласен с тем, что было бы много более эффективных способов сделать это, но я больше интересовался тем, как использовать аргументы переменной длины. Теперь он работает отлично. Спасибо за ваш вклад. – Bazooka