繁体   English   中英

function退出后char数组变量被销毁

[英]char array variables are destroyed after exiting from function

我使用strtok()在 function 中标记我的字符串。将值复制到全局char数组后,我打印这些值以确保功能。 一切都很好,但是当我想访问它们时,它们被破坏了。

这是代码:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

int client, count = 0;

volatile char *token_temp[30];
volatile int toknum = 0;

int text_test()
{
    char my_tokenised_string_buffer[255] = "Response\n\nCompany\nModel\nRevision: N01234567890\n\nOK";
    const char delimiters[3] = "\n";

    char *token = strtok(my_tokenised_string_buffer, delimiters);
    token_temp[0]= token;
    printf("first tokenised value = %s\n", token);

    while (token != NULL) {
        ++toknum;
        token = strtok(NULL, delimiters);
        token_temp[toknum]= token;
        printf("toknum : %d\t", toknum);
        printf("token id from inside tokenise loop : %s -> [%u]\n", token_temp[toknum], toknum);
    }
    printf("\n\n\n");
    for (int i = 0; i < toknum; i++) {
        printf("token [%d] value in function out of tokenise = %s\n", i, token_temp[i]);
    }
    return 0;
}

int main()
{
    text_test();
    printf("\n\n\n");

    for (int i = 0; i < toknum; i++) {
        printf("token [%d] value in main = %s\n", i, (char *)token_temp[i]);
    }
    return 0;
}

这是 output 在此处输入图像描述

我想将值分配给结构,但它们被遗漏了。

在 function 中声明了一个具有自动存储持续时间的本地数组

int text_test()
{
    char my_tokenised_string_buffer[255] = "Response\n\nCompany\nModel\nRevision: N01234567890\n\nOK";
//...

退出function后就不会活着了。

所以指针数组

volatile char *token_temp[30];

将包含无效指针并且取消引用这些指针将调用未定义的行为。

例如,您需要为从数组my_tokenised_string_buffer中提取的每个字符串动态分配一个字符数组。

另一种方法是将数组my_tokenised_string_buffer声明为具有 static 存储持续时间,指定关键字static

static char my_tokenised_string_buffer[255] = "Response\n\nCompany\nModel\nRevision: N01234567890\n\nOK";

问题是strtok调用给出了指向my_tokenised_string_buffer切片的指针。 但是通过退出 function, my_tokenised_string_buffer从 scope 中退出,因此被您放入堆栈的新数据覆盖。 为避免这种情况,您有两种解决方案:

或者my_tokenised_string_buffer永远不会出scope,做如下程序:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

int client, count =0;


volatile char *token_temp[30];
volatile int toknum = 0;
char my_tokenised_string_buffer[255] = "Response\n\nCompany\nModel\nRevision: N01234567890\n\nOK"; // Static, so won't go out of scope

int text_test()
{
    const char delimiters[3] = "\n";

    char *token = strtok(my_tokenised_string_buffer, delimiters);
    token_temp[0]= token;
    printf("first tokenised value = %s\n",token);

    while (token != NULL)
    {
        ++toknum ;
        token = strtok(NULL, delimiters);
        token_temp[toknum]= token;
        printf("toknum : %d\t",toknum);
        printf("token id from inside tokenise loop : %s -> [%u]\n", token_temp[toknum], toknum);
    }
    printf("\n\n\n");
    for(int i = 0; i < toknum;i++)
    {
        printf("token [%d] value in function out of tokenise = %s\n",i, token_temp[i]);
    }
    return 0;

}

int main()
{
    text_test();
    printf("\n\n\n");

    for(int i = 0; i < toknum;i++)
    {
        printf("token [%d] value in main = %s\n",i, token_temp[i]);
    }
    return 0;
}

或者您每次获得新令牌时都使用 malloc 复制您的令牌。但是,您需要以不同方式管理最后一个令牌:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

#include <stdlib.h>

int client, count = 0;


volatile char *token_temp[30];
volatile int toknum = 0;

int text_test()
{
    char my_tokenised_string_buffer[255] = "Response\n\nCompany\nModel\nRevision: N01234567890\n\nOK";
    const char delimiters[3] = "\n";

    char *token = strtok(my_tokenised_string_buffer, delimiters);

    token_temp[0] = malloc((1 + strlen(token)) * sizeof(char));
    strcpy((char*) token_temp[0], token);

    printf("first tokenised value = %s\n",token);

    while (token != NULL)
    {
        ++toknum ;
        token = strtok(NULL, delimiters);

        if (token != NULL) {
            token_temp[toknum] = malloc((1 + strlen(token)) * sizeof(char));
            strcpy((char*) token_temp[toknum], token);
        } else {
            token_temp[toknum] = NULL;
        }

        printf("toknum : %d\t",toknum);
        printf("token id from inside tokenise loop : %s -> [%u]\n", token_temp[toknum], toknum);
    }
    printf("\n\n\n");
    for(int i = 0; i < toknum;i++)
    {
        printf("token [%d] value in function out of tokenise = %s\n", i, token_temp[i]);
    }
    return 0;

}

int main()
{
    text_test();
    printf("\n\n\n");

    for(int i = 0; i < toknum;i++)
    {
        printf("token [%d] value in main = %s\n",i, token_temp[i]);
    }
    return 0;
}

strtok()是一个令人困惑且容易出错的 function。它返回的指针指向被标记化的字符串(为此目的进行了修改)。 将这些指针存储到全局数组(顺便说一句,不需要 ne volatile限定)会导致 function 返回后出现未定义的行为,因为数组my_tokenised_string_buffer不再有效。

您应该分配令牌的副本并将目标数组作为参数。

这是修改后的版本:

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

int text_test(char *token_temp[], int length) {
    char my_tokenised_string_buffer[] = "Response\n\nCompany\nModel\nRevision: N01234567890\n\nOK";
    const char delimiters[] = "\n";
    char *token;
    int toknum = 0;

    token = strtok(my_tokenised_string_buffer, delimiters);
    while (toknum + 1 < length && token != NULL) {
        token_temp[toknum++]= strdup(token);
        token = strtok(NULL, delimiters);
    }
    token_temp[toknum] = NULL; /* terminate the array with a null pointer */
    return toknum; /* return the number of tokens */
}

int main() {
    char *token_temp[30];
    int array_length = sizeof(token_temp) / sizeof(*token_temp);
    int toknum = 0;

    toknum = text_test(token_temp, array_length);

    /* print the tokens */
    for (int i = 0; i < toknum; i++) {
        printf("token [%d] value in main = %s\n", i, token_temp[i]);
    }
    /* free the tokens */
    for (int i = 0; i < toknum; i++) {
        free(token_temp[i]);
    }
    return 0;
}

您可以使用此代码来解决您的问题:

enter code here

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
//------------------------------------------------------------
int SpliteMessage(char* input , char sp , char token_temp[10][40])
{
    int len = strlen(input);
    int i,token_cnt=0,bcnt=0;
    for (i=0 ; i<len ; i++)
    {
        if (input[i] == sp)
        {
            token_temp[token_cnt][bcnt] = 0;
            token_cnt++;
            bcnt=0;
        }
        else
        {
            token_temp[token_cnt][bcnt] = input[i];
            bcnt++;
        }
    }
    return token_cnt;
}
//----------------------------------------------------------------
int main()
{
    char buffer[200] = "Response\n\nCompany\nModel\nRevision: N01234567890\n\nOK";
    char t_temp[10][40];
    int token_counter =  SpliteMessage(buffer , '\n' , t_temp);
    printf("\n--------------\n(Token Counter -> %i)\n",token_counter);
    for (int i=0 ; i<token_counter ; i++)
        printf("token[%i] from main: (%s) \n",i,t_temp[i]);
    return 0;
}

关于:

token_temp[toknum]= token;

这只是复制指针,实际需要的是复制数据,。

建议:

token_temp[ toknum ] = strdup( token );

这将创建数据的副本,然后将指向该副本的指针放入数组中

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM