如何正确释放数组而不出现错误?

发布于 2024-10-06 07:42:04 字数 3442 浏览 0 评论 0原文

我在 @GWW 的帮助下想出了这段代码,现在我无法释放 char**

这是我的代码(它只是读取输入文件并在屏幕上打印其中的名称):

    /*   deallocate2D
corresponding function to dynamically deallocate 2-dimensional array using
 * malloc.
 * accepts a char** as the "array" to be allocated, and the number of rows.
 * as with all dynamic memory allocation, failure to free malloc'ed memory
 * will result in memory leaks
 */
void deallocate2D(char** array, int nrows) {

    /*  deallocate each row  */
    int i;
    for (i = 0; i < nrows; i++) {
        free(array[i]);
    }

    /*  deallocate array of pointers  */
    free(array);
}

int readInputFile(FILE *fp, char **file_images) {
    num_lines = 0;
    int s = 10;
    char line[MAX_LENGTH];
    char **final_filenames;

    while (fgets(line, sizeof line, fp) != NULL) /* read a line */ {
        if (line[0] != '\n') {
            if (num_lines >= s) {
                s += 100;
                if ((file_images = (char**) realloc(file_images, s * sizeof (char*))) == NULL) {
                    printf("Error reallocating space for 2d array: %s\n", strerror(errno));
                    return -1;
                }
            }
            if ((file_images[num_lines] = malloc(MAX_LENGTH * sizeof (char))) == NULL) {
                printf("Error allocating space for 2d array: %s\n", strerror(errno));
                return -1;
            }

            strncpy(file_images[num_lines], line, MAX_LENGTH);
            if (file_images[num_lines] == NULL) {
                printf("Strncpy failed: %s\n", strerror(errno));
                return -1;
            }
            printf("name of file %d is: %s \n", num_lines, file_images[num_lines]);
            num_lines++;
        }
    }
    printf("Num_lines: %d\n",num_lines);
    //realloc to number of lines in the file, to avoid wasting memory
    if ((final_filenames = realloc(file_images, num_lines * sizeof (char*))) == NULL) {
        printf("Error reallocating space for 2d array: %s\n", strerror(errno));
        return -1;
    } else {
        file_images = final_filenames;
        deallocate2D(final_filenames, num_lines);
    }
    return 0;
    //don't forget to free lines 2d array! (here or at the end of the code)
}

int main(int argc, char *argv[]) {
    //pixel* image;
    char **images_filenames;

    //check parameters
    if (argc < 4) {
        printf("Incorrect usage.\nPlease use \"./invert input_filename.ppm charWidth charHeight \"\n");
        return -1;
    }

    printf("Opening input file [%s]\n", argv[1]);
    FILE *fpin = fopen(argv[1], "r");
    if (fpin == NULL) {
        printf("Could not open input file\n");
        return -1;
    }
    if ((images_filenames = ((char**) malloc(10 * sizeof (char*)))) == NULL) {
        printf("Error allocating initial space for 2d array: %s\n", strerror(errno));
        return -1;
    }

    if (readInputFile(fpin, images_filenames) == -1) {
        printf("Error reading image filenames from input\n");
        return -1;
    }

    fclose(fpin);
    printf("###########\n");

    deallocate2D(images_filenames, num_lines);

    printf("Done!\n");
    return 0;
}

所以,我不明白为什么我不能 free final_filenamesimages_filenames

这段代码给我的错误是:

*** glibc detected *** ./main: double free or corruption (!prev): 0x0986d228 ***

如何正确释放我的数组而不出现错误?

I came up with this code with the help of @GWW and now I can't free a char**.

Here's my code (it just reads an input file and prints the names in it on the screen):

    /*   deallocate2D
corresponding function to dynamically deallocate 2-dimensional array using
 * malloc.
 * accepts a char** as the "array" to be allocated, and the number of rows.
 * as with all dynamic memory allocation, failure to free malloc'ed memory
 * will result in memory leaks
 */
void deallocate2D(char** array, int nrows) {

    /*  deallocate each row  */
    int i;
    for (i = 0; i < nrows; i++) {
        free(array[i]);
    }

    /*  deallocate array of pointers  */
    free(array);
}

int readInputFile(FILE *fp, char **file_images) {
    num_lines = 0;
    int s = 10;
    char line[MAX_LENGTH];
    char **final_filenames;

    while (fgets(line, sizeof line, fp) != NULL) /* read a line */ {
        if (line[0] != '\n') {
            if (num_lines >= s) {
                s += 100;
                if ((file_images = (char**) realloc(file_images, s * sizeof (char*))) == NULL) {
                    printf("Error reallocating space for 2d array: %s\n", strerror(errno));
                    return -1;
                }
            }
            if ((file_images[num_lines] = malloc(MAX_LENGTH * sizeof (char))) == NULL) {
                printf("Error allocating space for 2d array: %s\n", strerror(errno));
                return -1;
            }

            strncpy(file_images[num_lines], line, MAX_LENGTH);
            if (file_images[num_lines] == NULL) {
                printf("Strncpy failed: %s\n", strerror(errno));
                return -1;
            }
            printf("name of file %d is: %s \n", num_lines, file_images[num_lines]);
            num_lines++;
        }
    }
    printf("Num_lines: %d\n",num_lines);
    //realloc to number of lines in the file, to avoid wasting memory
    if ((final_filenames = realloc(file_images, num_lines * sizeof (char*))) == NULL) {
        printf("Error reallocating space for 2d array: %s\n", strerror(errno));
        return -1;
    } else {
        file_images = final_filenames;
        deallocate2D(final_filenames, num_lines);
    }
    return 0;
    //don't forget to free lines 2d array! (here or at the end of the code)
}

int main(int argc, char *argv[]) {
    //pixel* image;
    char **images_filenames;

    //check parameters
    if (argc < 4) {
        printf("Incorrect usage.\nPlease use \"./invert input_filename.ppm charWidth charHeight \"\n");
        return -1;
    }

    printf("Opening input file [%s]\n", argv[1]);
    FILE *fpin = fopen(argv[1], "r");
    if (fpin == NULL) {
        printf("Could not open input file\n");
        return -1;
    }
    if ((images_filenames = ((char**) malloc(10 * sizeof (char*)))) == NULL) {
        printf("Error allocating initial space for 2d array: %s\n", strerror(errno));
        return -1;
    }

    if (readInputFile(fpin, images_filenames) == -1) {
        printf("Error reading image filenames from input\n");
        return -1;
    }

    fclose(fpin);
    printf("###########\n");

    deallocate2D(images_filenames, num_lines);

    printf("Done!\n");
    return 0;
}

So, I don't understand why can't I free final_filenames and images_filenames.

The error that this code gives me is:

*** glibc detected *** ./main: double free or corruption (!prev): 0x0986d228 ***

How do I correctly free my arrays without errors?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云柯 2024-10-13 07:42:04

问题是您正在释放一个可能已经被释放的指针,并且您不知道正在使用多少空间没有指向最近分配的空间的指针(通常)所以你不能准确地释放内存。在 main() 中,您:

char **images_filenames;                     

[...]                                

if ((images_filenames = ((char**) malloc(10 * sizeof (char*)))) == NULL) {

[...]

if (readInputFile(fpin, images_filenames) == -1) {

[...]

deallocate2D(images_filenames, num_lines);

分配 10 个字符指针,然后将该数组传递给 readInputFile() 函数。在该函数内部,有重新分配数组的代码,但您没有提供主程序知道新地址是什么的方法。这样做的方法是要么传递一个指针到您想要修改的任何内容,要么让函数返回修改后的值(或者您采取肮脏的做法,例如使用全局变量而不是参数 - 但您不应该这样做)。

因此,您需要:

if (readInputFile(fpin, &images_filenames) == -1) {

readInputFile() 函数中,您需要进行大量更改 - 处理三指针参数的大更改,以及各种编码问题:

int readInputFile(FILE *fp, char ***ppp_files)
{
    num_lines = 0;
    int s = 10;
    char line[MAX_LENGTH];
    char **file_images = *ppp_files;
    char **final_filenames;

更新:我没有注意到这只是初始化 num_lines,而不是声明它。因此,num_lines 必须是某种全局变量......下面的一些评论需要调整以允许这一点。


到目前为止,变化(几乎)微不足道;我们得到一个指向“char **”的指针,因此是三重指针参数。为了简化以下代码,请在旧名称 (file_images) 下创建参数的本地副本,并使用参数指向的值对其进行初始化。接下来的代码可以继续使用file_images;只需确保在返回之前更新参数即可。

除了...

您假设 s = 10',但实际上,您应该让 main 函数告诉您有多少行可用。它确实分配了 10 行,但如果不仔细检查的话,并不清楚情况是否如此。您应该让 main() 程序显示预先分配了多少行 - 函数的额外参数。您还面临这样的问题:main() 程序无法告诉 deallocate2D() 函数数组中有多少行,因为它不知道。目前尚不清楚您的代码如何编译;这里有一个局部变量 num_lines,但在 main() 中有一个对变量 num_lines 的引用,但没有声明。局部变量屏蔽任何全局变量。

    while (fgets(line, sizeof line, fp) != NULL) {
        if (line[0] != '\n') {
            if (num_lines >= s) {
                s += 100;

添加大量行是个好主意;它“摊销”重新分配的成本。

               if ((file_images = (char**) realloc(file_images, s * sizeof (char*))) == NULL)

不过,您使用的技术存在一些具体问题。
纯代码风格:当一行包含带有嵌入式赋值的 if 并且它变得太长时,请在条件之前将赋值拆分出来:

                file_images = (char**) realloc(file_images, s * sizeof (char*));
                if (file_images == NULL)

现在只剩下一个微妙的错误。如果realloc()失败会发生什么...

没错,你已经泄漏了内存,因为file_images中的值为空,所以没有办法释放它的内容用来指。 永远不要写

x = realloc(x, size);

失败时会泄漏内存!因此,您需要:

                char **new_space = realloc(file_images, s * sizeof (char*));
                if (new_space == NULL)
                {
                    printf("Error reallocating space for 2d array: %s\n",
                           strerror(errno));
                    *ppp_files = file_images;
                    return -1;
                }
            }

作为一般规则,错误消息应打印在 stderr 上;我还没修好这个

请注意,我小心地将 file_images 的最后一个(非空)值复制回主程序中的变量中。对大小也做同样的事情(另一个接口更改)可能是合适的,或者使用结构来封装数组 - 大小和指向其基数的指针。

        if ((file_images[num_lines] = malloc(MAX_LENGTH * sizeof (char))) == NULL)
        {
             printf("Error allocating space for 2d array: %s\n", strerror(errno));
             return -1;              
        }

此错误返回需要设置*ppp_files = file_images;

            strncpy(file_images[num_lines], line, MAX_LENGTH);


            if (file_images[num_lines] == NULL) {               
                printf("Strncpy failed: %s\n", strerror(errno));
                return -1;
            }                                                                   

这个测试很奇怪;您知道 file_images[num_lines] 不为 null,并且 strncpy() 不会改变这一点。您不需要测试和错误处理。

            printf("name of file %d is: %s \n", num_lines, file_images[num_lines]);
            num_lines++;
        }                                                              
    }
    printf("Num_lines: %d\n",num_lines);

好的...

    //realloc to number of lines in the file, to avoid wasting memory

手感很好。这几乎不值得;即使在 64 位机器上,您最多浪费不到 1 KiB。不过,保持整洁也没什么坏处——很好。

    if ((final_filenames = realloc(file_images, num_lines * sizeof (char*))) == NULL) {
        printf("Error reallocating space for 2d array: %s\n", strerror(errno));
        return -1;

同样,您需要在返回之前设置*ppp_files = file_images;

    } else {
        file_images = final_filenames;

这不会影响 main() 程序中的值。它需要再次是*ppp_files = file_images;

        deallocate2D(final_filenames, num_lines);

等等——你释放了所有精心分配的空间吗?所以你最终不会使用它吗?上面的赋值只是复制了一个指针值;它没有复制内存......

    }
    return 0;
    //don't forget to free lines 2d array! (here or at the end of the code)
}

这个评论是错误的 - 成功返回后,内存已经被释放。


让我猜一下 - 你不使用“vim”或其他“vi”衍生词进行编辑。在第 1 列中确实有其函数的左大括号的人,因为这样您就可以使用 ']]' 或 '在文件中向前或向后跳转到下一个或上一个函数的开头>[['。处理不起作用的代码是令人厌烦的。


嗯,这是一个开始的诊断...这是使用结构来转发文件名数组的工作代码。我使用从结构中复制的局部变量保留了 readInputFile() 函数的主体,并确保结构始终正确更新。

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

enum { MAX_LENGTH = 512 };

typedef struct FileNameArray
{
    size_t   nfiles;    /* Number of file names allocated and in use */
    size_t   maxfiles;  /* Number of entries allocated in array */
    char   **files;     /* Array of file names */
} FileNameArray;

static void deallocate2D(FileNameArray *names)
{
    for (size_t i = 0; i < names->nfiles; i++)
        free(names->files[i]);
    free(names->files);
    names->nfiles   = 0;
    names->files    = 0;
    names->maxfiles = 0;
}

static int readInputFile(FILE *fp, FileNameArray *names)
{
    int    num_lines  = names->nfiles;
    int    max_lines  = names->maxfiles;
    char **file_names = names->files;
    char line[MAX_LENGTH];
    char **final_filenames;

    while (fgets(line, sizeof line, fp) != NULL)
    {
        if (line[0] != '\n')
        {
            /* Remove newline from end of file name */
            char *nl = strchr(line, '\n');
            if (nl != 0)
                *nl = '\0';
            if (num_lines >= max_lines)
            {
                max_lines += 100;
                char **space = realloc(file_names, max_lines * sizeof (char*));
                if (space == NULL)
                {
                    fprintf(stderr, "Error reallocating space for 2d array: %s\n",
                            strerror(errno));
                    return -1;
                }
                names->maxfiles = max_lines;
                names->files = space;
                file_names = space;
            }
            if ((file_names[num_lines] = malloc(strlen(line) + 1)) == NULL)
            {
                fprintf(stderr, "Error allocating space for 2d array: %s\n",
                        strerror(errno));
                return -1;
            }
            names->nfiles++;
            strcpy(file_names[num_lines], line);
            printf("name of file %d is: %s \n", num_lines, file_names[num_lines]);
            num_lines++;
        }
    }

    printf("Num_lines: %d\n", num_lines);
    //realloc to number of lines in the file, to avoid wasting memory
    if ((final_filenames = realloc(file_names, num_lines * sizeof (char*))) == NULL)
    {
        fprintf(stderr, "Error reallocating space for 2d array: %s\n",
                strerror(errno));
        return -1;
    }
    names->maxfiles = num_lines;
    names->files    = final_filenames;
    return 0;
}

int main(int argc, char *argv[])
{
    FileNameArray names = { 0, 0, 0 };

    //check parameters
    if (argc < 4)
    {
        fprintf(stderr, "Usage: %s input_filename.ppm charWidth charHeight\n",
                argv[0]);
        return -1;
    }

    printf("Opening input file [%s]\n", argv[1]);
    FILE *fpin = fopen(argv[1], "r");
    if (fpin == NULL) {
        fprintf(stderr, "Could not open input file %s (%s)\n",
                argv[1], strerror(errno));
        return -1;
    }

    if ((names.files = malloc(10 * sizeof (char*))) == NULL)
    {
        fprintf(stderr, "Error allocating initial space for 2d array: %s\n",
                strerror(errno));
        return -1;
    }
    names.maxfiles = 10;

    if (readInputFile(fpin, &names) == -1)
    {
        fprintf(stderr, "Error reading image filenames from input\n");
        return -1;
    }

    fclose(fpin);
    printf("###########\n");

    deallocate2D(&names);

    printf("Done!\n");
    return 0;
}

The problems are that you are freeing a pointer that may already have been freed, and you don't know how much space is in use don't have a pointer to the most recently allocated space (in general) so you can't free the memory accurately. In main(), you have:

char **images_filenames;                     

[...]                                

if ((images_filenames = ((char**) malloc(10 * sizeof (char*)))) == NULL) {

[...]

if (readInputFile(fpin, images_filenames) == -1) {

[...]

deallocate2D(images_filenames, num_lines);

You allocate 10 character pointers, and then pass that array to the readInputFile() function. Inside that function, there is code to reallocate the array, but you have not provided a way for the main program to know what that new address is. The way you do that is either by passing a pointer to whatever it is you want modified, or you have the function return the modified value (or you resort to sordid practices like using global variables instead of parameters - but you shouldn't do that).

So, you need:

if (readInputFile(fpin, &images_filenames) == -1) {

And in the readInputFile() function, you need a whole lot of changes - the big one to deal with the triple-pointer argument, and then a variety of coding problems:

int readInputFile(FILE *fp, char ***ppp_files)
{
    num_lines = 0;
    int s = 10;
    char line[MAX_LENGTH];
    char **file_images = *ppp_files;
    char **final_filenames;

Update: I didn't notice that this was simply initializing num_lines, not declaring it. Thus, num_lines must be a global variable of some sort...some of the commentary below needs adjusting to allow for this.


So far, the change is (almost) trivial; we're getting a pointer to a 'char **', hence the triple pointer argument. To simplify the following code, make a local copy of the parameter under the old name (file_images) and initialized it with the value that the argument points at. Following code can then continue to work with file_images; just ensure that the argument is updated before returning.

Except...

You assume that 's = 10', but really, you should have the main function tell you how many rows were available. It did allocate 10 rows, but it is not clear without careful scrutiny that was the case. You should have the main() program say how many rows were preallocated - an extra argument to the function. You also face the problem that the main() program cannot tell the deallocate2D() function how many rows are in the array because it does not know. It is not clear how your code compiles; you have a local variable num_lines here, but there's a reference to a variable num_lines in main() for which there is no declaration. The local variable masks any global variable.

    while (fgets(line, sizeof line, fp) != NULL) {
        if (line[0] != '\n') {
            if (num_lines >= s) {
                s += 100;

Adding a large number of rows is a good idea; it 'amortizes' the cost of the reallocations.

               if ((file_images = (char**) realloc(file_images, s * sizeof (char*))) == NULL)

There are specific problems with the technique you've used though.
Pure code style: when a line contains an if with an embedded assignment and it gets too long, split the assignment out before the condition:

                file_images = (char**) realloc(file_images, s * sizeof (char*));
                if (file_images == NULL)

Now there's just a subtle bug left. What happens if realloc() fails...

That's right, you've leaked the memory because the value in file_images is null, so there is no way to release what it used to point to. Never write:

x = realloc(x, size);

It leaks memory on failure! Hence, you need:

                char **new_space = realloc(file_images, s * sizeof (char*));
                if (new_space == NULL)
                {
                    printf("Error reallocating space for 2d array: %s\n",
                           strerror(errno));
                    *ppp_files = file_images;
                    return -1;
                }
            }

As a general rule, error messages should be printed on stderr; I haven't fixed this.

Note that I carefully copied back the last (non-null) value of file_images into the variable in the main program. It might be appropriate to do the same with the size, too (another interface change), or use a structure to encapsulate the array - size and pointer to its base.

        if ((file_images[num_lines] = malloc(MAX_LENGTH * sizeof (char))) == NULL)
        {
             printf("Error allocating space for 2d array: %s\n", strerror(errno));
             return -1;              
        }

This error return needs to set *ppp_files = file_images;.

            strncpy(file_images[num_lines], line, MAX_LENGTH);


            if (file_images[num_lines] == NULL) {               
                printf("Strncpy failed: %s\n", strerror(errno));
                return -1;
            }                                                                   

This test is odd; you know that file_images[num_lines] is not null, and strncpy() doesn't change that. You don't need the test and error handling.

            printf("name of file %d is: %s \n", num_lines, file_images[num_lines]);
            num_lines++;
        }                                                              
    }
    printf("Num_lines: %d\n",num_lines);

OK...

    //realloc to number of lines in the file, to avoid wasting memory

Nice touch. It is barely worth it; even on a 64-bit machine, you are wasting less than 1 KiB at most. However, no harm in being tidy - good.

    if ((final_filenames = realloc(file_images, num_lines * sizeof (char*))) == NULL) {
        printf("Error reallocating space for 2d array: %s\n", strerror(errno));
        return -1;

Again, you need to set *ppp_files = file_images; before return.

    } else {
        file_images = final_filenames;

This does not affect the value in the main() program. It would need to be *ppp_files = file_images; again.

        deallocate2D(final_filenames, num_lines);

Hold on - you deallocate all your carefully allocated space? So you aren't going to use it after all? The assignment above merely copied a pointer value around; it did not make a copy of the memory...

    }
    return 0;
    //don't forget to free lines 2d array! (here or at the end of the code)
}

This comment is wrong - on successful return, the memory is already deallocated.


Lemme guess - you don't use 'vim' or another 'vi' derivative for editing. People who do have the opening brace of their functions in column 1, because then you can jump forwards or backwards through the file to the start of the next or previous function using ']]' or '[['. It is irksome working with code where that does not work.


Well, that's a starting diagnosis... Here's working code using a structure to relay the array of file names around. I've left the body of the readInputFile() function using local variables that are copied out of the structure, and ensured that the structure is properly updated at all times.

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

enum { MAX_LENGTH = 512 };

typedef struct FileNameArray
{
    size_t   nfiles;    /* Number of file names allocated and in use */
    size_t   maxfiles;  /* Number of entries allocated in array */
    char   **files;     /* Array of file names */
} FileNameArray;

static void deallocate2D(FileNameArray *names)
{
    for (size_t i = 0; i < names->nfiles; i++)
        free(names->files[i]);
    free(names->files);
    names->nfiles   = 0;
    names->files    = 0;
    names->maxfiles = 0;
}

static int readInputFile(FILE *fp, FileNameArray *names)
{
    int    num_lines  = names->nfiles;
    int    max_lines  = names->maxfiles;
    char **file_names = names->files;
    char line[MAX_LENGTH];
    char **final_filenames;

    while (fgets(line, sizeof line, fp) != NULL)
    {
        if (line[0] != '\n')
        {
            /* Remove newline from end of file name */
            char *nl = strchr(line, '\n');
            if (nl != 0)
                *nl = '\0';
            if (num_lines >= max_lines)
            {
                max_lines += 100;
                char **space = realloc(file_names, max_lines * sizeof (char*));
                if (space == NULL)
                {
                    fprintf(stderr, "Error reallocating space for 2d array: %s\n",
                            strerror(errno));
                    return -1;
                }
                names->maxfiles = max_lines;
                names->files = space;
                file_names = space;
            }
            if ((file_names[num_lines] = malloc(strlen(line) + 1)) == NULL)
            {
                fprintf(stderr, "Error allocating space for 2d array: %s\n",
                        strerror(errno));
                return -1;
            }
            names->nfiles++;
            strcpy(file_names[num_lines], line);
            printf("name of file %d is: %s \n", num_lines, file_names[num_lines]);
            num_lines++;
        }
    }

    printf("Num_lines: %d\n", num_lines);
    //realloc to number of lines in the file, to avoid wasting memory
    if ((final_filenames = realloc(file_names, num_lines * sizeof (char*))) == NULL)
    {
        fprintf(stderr, "Error reallocating space for 2d array: %s\n",
                strerror(errno));
        return -1;
    }
    names->maxfiles = num_lines;
    names->files    = final_filenames;
    return 0;
}

int main(int argc, char *argv[])
{
    FileNameArray names = { 0, 0, 0 };

    //check parameters
    if (argc < 4)
    {
        fprintf(stderr, "Usage: %s input_filename.ppm charWidth charHeight\n",
                argv[0]);
        return -1;
    }

    printf("Opening input file [%s]\n", argv[1]);
    FILE *fpin = fopen(argv[1], "r");
    if (fpin == NULL) {
        fprintf(stderr, "Could not open input file %s (%s)\n",
                argv[1], strerror(errno));
        return -1;
    }

    if ((names.files = malloc(10 * sizeof (char*))) == NULL)
    {
        fprintf(stderr, "Error allocating initial space for 2d array: %s\n",
                strerror(errno));
        return -1;
    }
    names.maxfiles = 10;

    if (readInputFile(fpin, &names) == -1)
    {
        fprintf(stderr, "Error reading image filenames from input\n");
        return -1;
    }

    fclose(fpin);
    printf("###########\n");

    deallocate2D(&names);

    printf("Done!\n");
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文