2016-04-17 3 views
-1

В моей функции заменить подстроку. Если входная подстрока длиннее исходной, она перемещает часть входной строки, чтобы освободить место для входной подстроки.Создание memmove() safe using realloc()

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

Я попробовал добавлять это до memmove():

char *newspc = (char*)realloc(in,len+sublen); 
in = newspc; 

Это разумная стратегия? Каков правильный способ освободить место для этой операции?

Вот программа без использования перераспределить():

#include <iostream> 
#include <string> 
#include <string.h> 

void replc(char* in, char* subin); 

int main() 
{ 
    char stmt[] = "replacing this $string ok"; 
    std::cout << stmt << "\n"; 
    replc(stmt, "longerstring"); //<<<4 characters longer breaks the program 
    std::cout << stmt << "\n"; 

} 

void replc(char* in, char* subin){ 
    uint8_t len = strlen(in); 
    uint8_t aftok = strchr(strchr(in, '$'), ' ')-in; 
    uint8_t dollar = strchr(in, '$')-in; 
    uint8_t tklen = aftok - dollar; 
    uint8_t sublen = strlen(subin); 

    if(sublen <= tklen){ 
    //enough room for substring 
    memmove(in+aftok-(tklen-sublen), in+aftok, (tklen-sublen)+1); 
    memcpy(in+dollar, subin, sublen); 
    in[len-(tklen-sublen)] = '\0'; 
    } 
    else{ 
    //not enough room for substring 
    // memory allocation should take place here? 
    memmove(in+aftok+(sublen-tklen), in+aftok, (sublen-tklen)+1); 
    memcpy(in+dollar, subin, sublen); 
    in[len+(sublen-tklen)] = '\0'; 
    } 

} 
+2

* Я думал, что любой индекс за пределами строки будет нераспределенной памятью. Если я увеличиваю длину входной подстроки на несколько символов, программа не сработает. * - Неопределенное поведение, простое и простое. Вы получаете доступ к массиву за пределами границ, тогда все может случиться, в том числе «работать». – PaulMcKenzie

+0

Я изменил вопрос в свете этой ссылки. – oraz

+1

Почему бы просто не использовать 'std :: string' для этого? Я знаю, что вы в конце концов выясните «волшебный код», чтобы получить это исправление, поскольку все, что он делает, - это делать вещи с помощью буферов и указателей. Но что вы получаете от этого, кроме как исправить ошибку? Просто используйте 'std :: string', если вы цените свое время. Черт, вы даже включили '', но ничего не использовали в нем. – PaulMcKenzie

ответ

1

Во-первых, если вы хотите использовать перераспределить, вы не должны использовать memmove, так как перераспределить будет заботиться о копировании данных.

От человека:

Функция перераспределить() изменяет размер блока памяти указывает на от PTR до байтов размера. Содержимое будет оставаться неизменным в диапазоне от до начала региона до минимума старого и нового размеров.

Кроме того, вы можете использовать только перераспределить на указателе ранее возвращенного таНос, перераспределить или calloc

Если PTR не NULL, то он должен быть возвращен более ранним вызовом таНос(), calloc() или realloc().

Таким образом, вы должны использовать таНос в главном

char *stmt = malloc(strlen("replacing this $string ok") + 1); 
if (stmt) 
    stmt = "replacing this $string ok"; 

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

пример C-стиль для прототипа:

void replc(char** in, char* subin); 

Allocation (с NewSize в виде целого числа):

*in = realloc(*in, NewSize); 

(Имейте в виду, что таНос и перераспределить может возвращать NULL, если распределение не в состоянии)

+0

Кажется, у меня было несколько вещей, чтобы узнать о функциях -alloc, но это помогло. Параметр, который я использовал, был: '(char * & in, ...' и выделен символом 'char * p = (char *) calloc (len + sublen, sizeof (char));' – oraz

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