簡體   English   中英

分配字符串時出現分段錯誤

[英]segmentation fault while assigning string

void getAgentInfo( char** agent_address )
{
    #define MAX_IP_SIZE 100
    FILE *fcfg=NULL;
    char line[MAXLINE];
    char *p , *pend;
    int findlen_ips, findlen_num;
    findlen_ips = strlen (findkey_ips);
    findlen_num = strlen (findkey_num);
    int iCount = 1; //in agent array entry
    fcfg = fopen (FCFG, "r");

    while (p = fgets (line, MAXLINE, fcfg))
    {
        //printf ("Looking at %s\n", p);
        if (p = findval (line, findkey_num, findlen_num))
        {
            pend = p + strlen (p) - 1;  /* check last char for newline terminator */
            if (*pend == '\n')
                *pend = 0;
            printf ("%s\n", p); /* process/parse the value */
            NumOfIp = atoi(p);
            //agent_address = (char*)calloc(NumOfIp + 1, sizeof(char));
            agent_address = new char*[NumOfIp + 1];
            for(int icount = 0; icount < NumOfIp+1; icount++)
            {
                agent_address[icount] = new char[MAX_IP_SIZE];
            }
        }

        if (p = findval (line, findkey_ips, findlen_ips))
        {
            pend = p + strlen (p) - 1;  /* check last char for newline terminator */
            if (*pend == '\n')
                *pend = 0;
            printf ("addr = %s\n", p); /* process/parse the value */
            agent_address[iCount]= p; //strcpy(agent_address[iCount], p)
            //printf("agent_address[iCount++]=%s\n",agent_address[iCount]);
            iCount++;
        }
    }
}

從上面的代碼中,我正在讀取一個txt文件,並在一個int var中獲取值,並根據該值創建2d字符串數組以存儲值:

... char ** agent_address = NULL; getAgentInfo(agent_address); TRACE_STR(“ \\ n”); agent_address [0] = MasterCPMAddr; ....

我成功地從行agent_address[0] = MasterCPMAddr;獲取了字符串agent_address[0] = MasterCPMAddr; 但是在我存儲它之后,我遇到了分割錯誤; //嘗試使用strcpy(agent_address[0], MasterCPMAddr)

在c中,參數按值傳遞。 因此要將agent_address傳遞給您的函數,您需要像這樣聲明它:

void getAgentInfo(char*** agent_address )
{

然后在函數內取消引用agent_address
目前, agent_address中的agent_address只是一個局部變量。

注意
您的代碼似乎是C,只是散布了C ++。 我建議您選擇一面。 用C或C ++編寫。 后者提供了一個健壯的庫,可以為您處理文件IO的實質和內存管理。 在此處將std::vector<std::string>傳遞給您的函數很有意義。 解決您的問題的一種更C ++風格將是:

int read_lines(std::vector<std::string>& lines)
{
    int count_lines = 0;
    std::string line;
    std::ifstream infile("file.txt");
    while (std::getline(infile, line))
    {
        lines.push_back(line);//add line to vector
        ++count_lines;
    }
    return count_lines;
}

完整的,經過測試的工作示例:

#include <iostream> 
#include <fstream>
#include <vector>

using namespace std;//to get rid of that pesky std::

int read_lines(vector<string>& lines)
{
    int count_lines = 0;
    string line;
    ifstream infile("file.txt");
    while (getline(infile, line))
    {
        lines.push_back(line);//add line to vector
        ++count_lines;
    }
    return count_lines;
}

int main ( void )
{
    vector<string> list;
    int lines_read = read_lines(list);
    int i=1;
    cout << "Read " << lines_read << " lines" << endl;
    //from start to finish
    for (vector<string>::iterator it = list.begin(); it != list.end(); ++it)
        cout << "Line: " << i++ << " "<< *it << endl;
    return 0;
}

如果您想使用老式的C-way進行操作,那么這就是我對您的問題的解答:

您的行為不確定。 getAgentInfo函數內部,您有一個指向字符串的指針( ppend )。 但是,這些指針僅在函數內有效。 您必須將實際的字符串復制到agent_address變量(使用strcpystrncpy )。
確保分配了存儲該字符串所需的內存,並向我們展示如何將變量傳遞給該字符串。 一個將多個字符串分配給char指針數組的純C函數可能看起來像這樣:

int read_lines(char *store_lines[], size_t max_lines)
{
    int i=0;
    size_t len;
    char buffer[200];//temp buffer
    FILE *fp = fopen("file.txt", "r");
    if (fp == NULL)|
        return -1;//error
    while (i < max_lines && fgets(buffer, sizeof buffer, fp) != NULL)
    {//read lines while we haven't reached the max, and there are lines to read
        len = strlen(buffer);
        store_lines[i] = malloc(len+1);//allocate memory
        if (store_lines[i] == NULL)
        {
            fclose(fp);//ALWAYS fclose
            return 0;//failed to allocate enough memory
        }
        *store_lines[i] = '\0';//set to empty
        strncat(store_lines[i], buffer, len);
        ++i;//next line
    }
    fclose(fp);
    return i;//return number of lines read
}

您可以使用如下數組的指針來調用此函數:

char *data[10];
int check = read_lines(data, 10);
if (check == -1)
{
    fprintf(stderr, "unable to open file");
    exit(1);
}
if (check == 0)
{
    fprintf(stderr, "failed to allocate memory\n");
    for (int i=0;data[i] != NULL;++i)
        fprintf(stderr, "Read line %d: %s\n", i+1, data[i]);//allocated memory vs null-pointers, possible to free memory here
    exit(1);
}
printf("Read %d lines out of %d\n", check, sizeof data/sizeof *data);
for (int i=0;i<check;++i)
{
    printf("Line %d: %s\n", i+1, data[i]);
    free(data[i]);
    data[i] = NULL;
}
return 0;

如果您還希望read_lines函數自己分配數組,則必須將指針的地址傳遞給指針(三個級別的間接尋址)。 但是,為了您自己以及您所愛的人,請盡可能避免:

int read_lines(char ***store_lines)
{
    char buffer[200],
        **target = *store_lines;//makes it easier
    size_t len, i;
    FILE *fp = fopen("file.txt", "r");
    if (fp == NULL)
        return -1;
    while(fgets(buffer, sizeof buffer, fp))
    {
        len = strlen(buffer);
        realloc(target, (1+i)*sizeof *target);//re-allocate memory for pointer array
        if (target == NULL)
        {
            fclose(fp);
            return 0;
        }
        target[i] = malloc(len+1);//allocate space for chars
        if (target[i] == NULL)
        {
            fclose(fp);
            return 0;
        }
        *target[i] = '\0';//empty string, enable strncat use
        strncat(target[i], buffer, len);
        ++i;//next line
    }
    fclose(fp);
    return (int) i;//cast to int - optional
}

您可以這樣調用此函數:

char **data = NULL;
int lines_read = read_lines(&data);
if (lines_read == -1)
{
    fprintf(stderr, "Could not open file");
    exit (EXIT_FAILURE);
}
if (lines_read == 0)
{
    fprintf(stderr, "Not enough RAM");
    exit (EXIT_FAILURE);
}
for (int i=0;i<lines_read;++i)
    printf("%d) %s\n", i, data[i]);//print out line-by-line
//free memory

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM