阅读背景:

使用realloc后,数组中的下一个指针将丢失

来源:互联网 
void operation2(char **p, int n, char *sir) {
    int i, move, k, xlen, ylen;
    char *x, *y, *q, separatori[] = " \'\",!?";
    x = strtok(sir, " ");
    y = strtok(NULL, " ");
    xlen = strlen(x);
    ylen = strlen(y);
    move = ylen - xlen;
    for (i = 0; i < n; i++) {
        k = 0;
        while (strstr(p[i] + k, x)) {
            q = strstr(p[i] + k, x);
            if ((strchr(separatori, *(q - 1)) || q == p[i]) &&
                (*(q + xlen) == '
void operation2(char **p, int n, char *sir) {
    int i, move, k, xlen, ylen;
    char *x, *y, *q, separatori[] = " \'\",!?";
    x = strtok(sir, " ");
    y = strtok(NULL, " ");
    xlen = strlen(x);
    ylen = strlen(y);
    move = ylen - xlen;
    for (i = 0; i < n; i++) {
        k = 0;
        while (strstr(p[i] + k, x)) {
            q = strstr(p[i] + k, x);
            if ((strchr(separatori, *(q - 1)) || q == p[i]) &&
                (*(q + xlen) == '\0' || strchr(separatori, *(q + xlen)))) {
                if (move > 0 && k == 0)
                    p[i] = realloc(p[i], (strlen(p[i]) + move * counter(p[i], x) + 1) * sizeof(char));
                q = strstr(p[i] + k, x);
                memmove(q + xlen + move, q + xlen, strlen(q + xlen) + 1);
                memcpy(q, y, ylen);
                k = strlen(p[i]) - strlen(q) + ylen;
                if (move < 0)
                    p[i] = realloc(p[i], (strlen(p[i]) + move + 1) * sizeof(char));
            } else
                k = k + xlen;
        }
        puts(p[i]);
    }
}

The code aims to find and replace a word (x) with a second one (y) in a text dynamically allocated in **p. They come in a string (sir) and are separated. move stores the difference between the words that are obtained. n represents the number of lines in the text.

该代码旨在用** p中动态分配的文本中的第二个(y)来查找和替换单词(x)。他们串起来(先生)并分开。移动存储获得的单词之间的差异。 n表示文本中的行数。

The word x must not be within another word hence the need to check for the separators.

单词x不能在另一个单词内,因此需要检查分隔符。

If the conditions are met then the string is reallocated depending if the move is positive or negative. If it's positive the string will be longer and can be reallocated for all the apparitions of the word x inside of it. counter is a function that counts the apparitions in the string. When move is negative the string must be diminished so the reallocation is done after the operations take place.

如果满足条件,则根据移动是正还是负来重新分配字符串。如果它是正数,则字符串将更长,并且可以为其中的单词x的所有显示重新分配。 counter是一个计算字符串中的外观的函数。当移动为负时,必须减少字符串,以便在操作发生后重新分配。

The replace is done with memmove and memcpy.

替换是使用memmove和memcpy完成的。

k is the position after the apparitions of x.

k是x的幻影之后的位置。

During a test there was the need to replace "o" with "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".

在测试期间,需要将“o”替换为“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”。

This is the reference Reference

这是参考参考

And this is what I get Result

这就是我得到的结果

When replacing "o" in the middle of the string an error occurs and the pointer to the next line is lost, pointing to the ending part of the previous line. The 1 represents the value of the counter for the line that follows

当在字符串中间替换“o”时,会发生错误,指向下一行的指针将丢失,指向上一行的结尾部分。 1表示后面一行的计数器值

Does realloc use memory that was already allocated and by doing so the next pointer is lost?

realloc是否使用已经分配的内存,这样下一个指针就会丢失?

EDIT: Here is the allocation of the array:

编辑:这是数组的分配:

int n, i;
scanf("%d", &n);
char **p, *aux;
p = malloc(n * sizeof(char *));
aux = malloc(12000 * sizeof(char));
getchar();
for (i = 0; i < n; i++) {
    fgets(aux, 12000, stdin);
    p[i] = malloc((strlen(aux) + 1) * sizeof(char));
    strcpy(p[i], aux);
    p[i][strlen(p[i]) - 1] = '\0';
}
free(aux);

2 个解决方案

#1


2  

Your code is very confusing because of too many side effects, redundant calls to strlen...

您的代码非常混乱,因为副作用太多,对strlen的冗余调用......

The main issue is you do not allocate enough space for your strings: you forget the extra byte needed for the '\0' terminator.

主要问题是你没有为字符串分配足够的空间:你忘记了'\ 0'终结符所需的额外字节。

You make this mistake in the main routine when you parse the file.

解析文件时,您在主例程中犯了这个错误。

You make it again when you reallocate the line.

重新分配线时再次进行。

You also forget to include the null byte when you memmove the contents of the line.

当您记住该行的内容时,您也忘记包含空字节。

Fix these issues first. There might be other ones, but you need to simplify your code to see them. Read all the comments, there are many hints.

首先解决这些问题。可能还有其他的,但您需要简化代码才能看到它们。阅读所有评论,有很多提示。

EDIT: You fixed your code in place, which may confuse other readers of this question, but you still have a mistake in the second call to realloc:

编辑:你修复了你的代码,这可能会使这个问题的其他读者感到困惑,但你在第二次调用realloc时仍然有错误:

p[i] = realloc(p[i], (strlen(p[i]) + move + 1) * sizeof(char));

is incorrect because you already shortened the line, therefore strlen(p[i]) is the new length. Simply write:

是不正确的,因为你已经缩短了行,因此strlen(p [i])是新的长度。只需写:

p[i] = realloc(p[i], strlen(p[i]) + 1);

EDIT: Here is simpler version of operation2 with fixes for most remarks in comments. I am not using count because since you did not post the code, I cannot assert that is does the right thing.

编辑:这是更简单的operation2版本,修复了注释中的大多数备注。我没有使用count,因为你没有发布代码,我不能断言这是正确的事情。

void operation2(char **p, int n, char *sir) {
    int i, move, k, xlen, ylen;
    static const char separatori[] = " \'\",!?";
    char *x, *y, *q;

    x = strtok(sir, " ");
    y = strtok(NULL, " ");
    xlen = strlen(x);
    ylen = strlen(y);
    move = ylen - xlen;
    for (i = 0; i < n; i++) {
        k = 0;
        while ((q = strstr(p[i] + k, x)) != NULL) {
            k = q - p[i];
            if ((q == p[i] || strchr(separatori, q[-1])) &&
                (q[xlen] == '\0' || strchr(separatori, q[xlen]))) {
                if (move > 0) {
                    p[i] = realloc(p[i], strlen(p[i]) + move + 1);
                    q = p[i] + k;
                }
                memmove(q + ylen, q + xlen, strlen(q + xlen) + 1);
                memcpy(q, y, ylen);
                k += ylen;
                if (move < 0) {
                    p[i] = realloc(p[i], strlen(p[i]) + 1);
                }
            } else {
                k += xlen;
            }
        }
        puts(p[i]);
    }
}

#2


0  

As far as the C Standard is concerned, the behavior of realloc in all cases where it succeeds is equivalent to copying the memory block to some arbitrary location, calling free upon it, calling malloc to create a new block of the requested size, and returning a pointer to the new block (in cases where the malloc wouldn't succeed, realloc is defined to return null without disturbing the original block). While many compilers usefully allowed a pointer to the old block to be compared with the new one, and would regard the difference between two pointers to the same object as being immutable and observable forever even after the lifetime of the object in question, the C Standard provides no means of querying whether a particular compiler supports such useful extensions.

就C标准而言,realloc在其成功的所有情况下的行为等同于将内存块复制到某个任意位置,在其上调用free,调用malloc以创建所请求大小的新块,并返回指向新块的指针(在malloc不成功的情况下,realloc被定义为返回null而不会干扰原始块)。虽然许多编译器有用地允许将旧块的指针与新块进行比较,并且将指向同一对象的两个指针之间的差异视为永久不可变和可观察的,即使在所讨论的对象的生命周期之后,C标准也是如此。没有提供查询特定编译器是否支持这种有用扩展的方法。

As a result, if one wants code to be compatible with aggressive compilers, one must refrain from having any pointers point within an object which is going to be realloc'ed unless one can guarantee that such pointers will never even be examined after a successful realloc takes place.

因此,如果希望代码与主动编译器兼容,则必须避免在将要重新分配的对象中指向任何指针,除非可以保证在成功重新分配之后甚至不会检查这样的指针发生了。


' || strchr(separatori, *(q + xlen)))) { if (move > 0 && k == 0) p[i] = realloc(p[i], (strlen(p[i]) + move * counter(p[i], x) + 1) * sizeof(char)); q = strstr(p[i] + k, x); memmove(q + xlen + move, q + xlen, strlen(q + xlen) + 1); memcpy(q, y, ylen); k = strlen(p[i]) - strlen(q) + ylen; if (move < 0) p[i] = realloc(p[i], (strlen(p[i]) + move + 1) * sizeof(char)); } else k = k + xlen; } puts(p[i]); } } void operation2(char **p, int n, char *sir) {



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: