链式strep给出了分段错误-C

链式strep给出了分段错误-C,c,string,segmentation-fault,strtok,strsep,C,String,Segmentation Fault,Strtok,Strsep,我试图创建一个字符串数组,以准备在表中显示它们 因此,我有一个函数,它返回一个缓冲字符串,其中包含一些扫描的wifi接入点列表,我使用strep将其按“\n”拆分,然后再按“\t”拆分 循环一直正常运行,直到到达末尾,当对while参数((line=strep(&buf,“\n”))求值时,它会给出一个SEGFAULT 根据@Jabberwocky询问的简短示例: #include <stdio.h> #include <stdlib.h> #include <st

我试图创建一个字符串数组,以准备在表中显示它们

因此,我有一个函数,它返回一个缓冲字符串,其中包含一些扫描的wifi接入点列表,我使用
strep
将其按
“\n”
拆分,然后再按
“\t”
拆分

循环一直正常运行,直到到达末尾,当对
while
参数
((line=strep(&buf,“\n”))
求值时,它会给出一个
SEGFAULT

根据@Jabberwocky询问的简短示例:

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

static int
wap_scan_count_lines(char*      wap_scan)
{
    int   line_amount = 0;
    char *scan = wap_scan;

    while(*scan)
    {
        if ('\n' == *scan){
            line_amount++;
        }
        scan++;
    }
    return line_amount;
}

int main() {

    char ***scan_result, *line=NULL, *item=NULL, *scan=NULL;
    scan = strdup("bssid / frequency / signal level / flags / ssid\n"
                  "a8:6a:bb:e2:d6:ef       5785    -47     [WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]       Fibertel WiFi114 5.8GHz");
    int wap_scan_size = wap_scan_count_lines(scan);
    scan_result = malloc(wap_scan_size * sizeof(**scan_result));
    int i = 0;
    int item_len = sizeof (*scan_result);

    while((line = strsep(&scan, "\n")) != NULL ) {
        if(i==0){
            i++;
            continue;
        }
        char **scan_line = calloc(5, item_len);
        int j = 0;
        while ((item = strsep(&line, "\t")) != NULL) {
            printf("%s\n", item);
            scan_line[j++] = strdup(item);
        }
        scan_result[i++] = scan_line;
    }
    return 0;
}
#包括
#包括
#包括
静态整数
wap\u扫描\u计数\u行(字符*wap\u扫描)
{
int line_amount=0;
字符*扫描=wap\u扫描;
while(*扫描)
{
如果('\n'==*扫描){
行_金额++;
}
扫描++;
}
返回行金额;
}
int main(){
字符***扫描结果,*行=NULL,*项=NULL,*扫描=NULL;
scan=strdup(“bssid/频率/信号电平/标志/ssid\n”
“a8:6a:bb:e2:d6:ef 5785-47[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]Fibertel WiFi114 5.8GHz”);
int wap_scan_size=wap_scan_count_行(扫描);
扫描结果=malloc(wap扫描大小*大小(**扫描结果));
int i=0;
int item_len=sizeof(*扫描结果);
while((line=strep(&scan,“\n”)!=NULL){
如果(i==0){
i++;
继续;
}
字符**扫描行=calloc(5,项目长度);
int j=0;
while((item=strep(&line,“\t”)!=NULL){
printf(“%s\n”,项);
扫描行[j++]=strdup(项目);
}
扫描结果[i++]=扫描线;
}
返回0;
}
真正给我带来问题的函数是:

char *** wifi_client_get_wap_list(int *len)
{
    char ***scan_result;
    char *buf, *buf_free, *cmd, *line, *item;
    int ret, items_len;
    cmd = strdup("SCAN");
    ret = wpa_ctrl_command(cmd, NULL);
    if (ret < 0) goto error;

    cmd = strdup("SCAN_RESULTS");
    ret = wpa_ctrl_command(cmd, &buf); //RETURNS A STRING ON BUF ALLOCATED BY STRDUP
    if (ret < 0){
        free(buf);
        goto error;
    }

    *len = wap_scan_count_lines(buf); //NUMBER OF LINES IN THE SCAN RESULT
    scan_result = calloc(*len, sizeof(**scan_result));
    int i = 0, j;
    buf_free = buf;
    items_len = sizeof (*scan_result);

    while ((line = strsep(&buf, "\n"))){ //THIS GIVES THE SEGFAULT AT THE END
        // SKIP FIRST LINE WITH HEADERS
        if (i==0){
            i++;
            continue;
        }

        //if (strcmp(line, "") == 0) {
        //  break;   
        //}

       //EACH LINE HAS 5 VALUES (bssid, freq, level,flags,ssid)
        char **scan_line = calloc(5, items_len); 
        j = 0;
        printf("INNER STEPS:\n");
        while((item = strsep(&line, "\t"))){
            *(scan_line + j) = strdup(item);
            printf("%d ", j);
            j++;
        }
        *(scan_result + i) = scan_line;
        printf("\nSTEP: %d\n", i);
        i++;
    }

    free(buf_free);
    free(cmd);
    return scan_result;

    error:
    // @TODO: Handle error
    if (ret == -2) {
        printf("'%s' command timed out.\n", cmd);
    } else if (ret < 0) {
        printf("'%s' command failed.\n", cmd);
    }

    free(cmd);
    return NULL;
}
char***wifi\u客户端\u获取\u wap\u列表(int*len)
{
字符***扫描结果;
字符*buf、*buf_free、*cmd、*line、*item;
内部检索,项目长度;
cmd=strdup(“扫描”);
ret=wpa\u ctrl\u命令(cmd,NULL);
如果(ret<0)转到错误;
cmd=strdup(“扫描结果”);
ret=wpa\u ctrl\u命令(cmd,&buf);//返回由STRDUP分配的buf上的字符串
如果(ret<0){
免费(buf);
转到错误;
}
*len=wap_scan_count_lines(buf);//扫描结果中的行数
扫描结果=calloc(*len,sizeof(**扫描结果));
int i=0,j;
buf_free=buf;
项目长度=尺寸(*扫描结果);
而((line=strep(&buf,“\n”)){//这将在末尾给出SEGFAULT
//跳过带有标题的第一行
如果(i==0){
i++;
继续;
}
//如果(strcmp(行“”)==0){
//中断;
//}
//每行有5个值(bssid、freq、level、flags、ssid)
字符**扫描行=calloc(5个项目);
j=0;
printf(“内部步骤:\n”);
while((item=strep(&line,“\t”)){
*(扫描行+j)=标准件(项目);
printf(“%d”,j);
j++;
}
*(扫描结果+i)=扫描线;
printf(“\n步骤:%d\n”,i);
i++;
}
免费(免费);
免费(cmd);
返回扫描结果;
错误:
//@TODO:Handle错误
如果(ret==-2){
printf(“%s”命令超时。\n”,cmd);
}否则如果(ret<0){
printf(“%s”命令失败。\n”,cmd);
}
免费(cmd);
返回NULL;
}
基于此问题,循环将比您希望的多运行一次,从而导致扫描结果溢出

文件的相关部分包括:

   The strsep() function returns a pointer to the token, that is, it
   returns the original value of *stringp.

wap\u scan\u count\u line中,计算以“\n”结尾的行数

int wap_scan_size = wap_scan_count_lines(scan);
scan_result = malloc(wap_scan_size * sizeof(**scan_result));
在下面的两行中,根据以“\n”结尾的行数分配内存以保存结果

int wap_scan_size = wap_scan_count_lines(scan);
scan_result = malloc(wap_scan_size * sizeof(**scan_result));
但是,上面引用的stresp()文档表明,在您的简化示例中,调用stresp的第一次wap\u scan\u size时,在调用结束时,结果将不会为NULL,并且在调用期间,scan不会设置为NULL。下次通过调用时,scan将在调用期间设置为NULL,但结果不会为NULL。这意味着循环主体将执行wap\u scan\u size+1次,导致写入超过scan\u结果的结尾

至少有两种可能的修复方法,这取决于您是否确实要处理输入末尾未以“\n”终止的任何行

如果您确实需要处理这样的行,这对我来说似乎更可靠,特别是考虑到您的简化示例以这样的行结尾,只需在扫描结果中分配一个额外的条目即可:

scan_result = malloc((wap_scan_size + 1) * sizeof(**scan_result));
如果您非常确定不需要处理这些行,但我认为这不正确,请更改:

while((line = strsep(&scan, "\n")) != NULL ) {


很难读懂***指针,我建议使用结构体。@Emreİriş是的,我知道,但***使迭代更简单。@WeatherVane我想是8,但老实说,我只是使用了另一个答案的代码。我想为这个字符串数组分配内存。因此,首先我使用
calloc(*len,sizeof(**scan_result))为“outer”数组分配内存
然后为每个“内部”数组分配char
**scan\u line=calloc(5,items\u len)。因此,第二个数组将是一个由5个**指针组成的数组。这可能需要很多工作才能解开。你的指向指针等的指针看起来很混乱。从
char****
char**
(char**)&scan
不可能正确,而且几乎所有
malloc/calloc
调用似乎都分配了错误类型或大小的对象。谢谢!!,我真的很感激。谢谢你花时间解释。
for(line = strsep(&scan, "\n"); scan != NULL; line = strsep(&scan, "\n") ) {