分段错误:循环打印时为 11

Posted

技术标签:

【中文标题】分段错误:循环打印时为 11【英文标题】:Segmentation fault: 11 when printing out of a loop 【发布时间】:2013-10-14 11:14:15 【问题描述】:

首先说我一直在找网络上的资料,用gdb调试做测试……什么都没有……我还是不明白这个错误,我猜想它可能来自“ getline" 指令,但我不确定...

代码的主要思想是逐行读取chars字符串转换为浮点数并将浮点数保存在一个名为nfloat的数组中,然后调用函数:*create_table*创建一个vector类型的指针数组.

输入是一个.txt,其中包含:n = 字符串的数量,在这种情况下 n = 3

3
[9.3,1.2,87.9]
[1.0,1.0]
[0.0,0.0,1.0]

第一个数字3 是我们在图像中看到的向量的数量,但该数字不是静态的,输入可以是57 等,而不是3

到目前为止,我已经开始执行以下操作,但我认为代码存在一些内存错误:

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


typedef struct 
    float* data;
    int size;
 vector;




vector *create_vector(int n, float* comps)
    vector newvect;
    newvect.data = (float *) malloc(n*sizeof(float));
    int i;
    for(i = 0; i < n; i++) 
        newvect.data[i] = comps[i];
        printf("Newvec.data[%d] = %.1f\n", i, newvect.data[i]);
    
    newvect.size = n;
    vector *pointvector;
    pointvector = &newvect;
    return(pointvector);



int NumsVector(char *linea, ssize_t size)
    int numsvector = 1; 
    int n;
    for(n = 2; n<= size; n++) 
        if (linea[n] != '[' && linea[n] != ']')
            if(linea[n] == 44)
                numsvector = numsvector + 1;
            
        
    
    return numsvector;


int main()
    int n, i;
    scanf("%d\n", &n);
    vector *v[n];
    for(i = 0; i<n; ++i)  
        char *line = NULL; 
        size_t len = 0;
        ssize_t read; 
        read = getline(&line,&len,stdin);
        int numsvector = NumsVector(line, read);
        float nfloat[numsvector];
        int j = 0;
        /* Replaces the end ] with a , */
        line[strlen(line) - 1] = ',';

        /* creates a new pointer, pointing after the first [ in the original string */
        char *p = line + 1;
        do
        
            /* grabs up to the next comma as a float */
            sscanf(p, "%f,", &nfloat[j]);
            /* moves pointer forward to next comma */
            while (*(p++) != ',');
        
        while (++j < numsvector); /* stops when you've got the expected number */
        v[i] = create_vector(numsvector, nfloat);
        printf("%f\n", v[i]->data[1]); //prints ok :)!
        free(line);
    
    printf("%f\n", v[i]->data[1]); //segmentation fault:11 :(!! 

好吧,我认为 printf 指令会出现问题,当我在循环内打印时,一切正常,但是当我尝试在 for 循环外执行相同操作时,它会打印分段错误错误......可能是内存泄漏?

了解 *v[n] 是否被很好地实现并很好地存储信息对我来说很重要,以便继续根据 *v[n] 信息创建函数。

当我打印出循环时,请有人帮我理解问题出在哪里?

【问题讨论】:

您的 create_vector() 函数正在返回一个局部变量的地址。 【参考方案1】:
vector *pointvector;
pointvector = &newvect;
return(pointvector);

您正在返回指向局部变量的指针。这是不正确的,需要通过为newvect 分配动态内存或在函数中使用static 变量然后复制数据来更改(数据不会在两次调用之间持续存在)。

编辑:根据要求,动态分配示例:

vector *create_vector(int n, float* comps)
    vector *newvect = malloc(sizeof(*newvect));
    newvect->data = malloc(n*sizeof(float));
    memcpy(newvect->data, comps, sizeof(float) * n);
    newvect->size = n;
    return newvector;

当然在某些时候你需要释放数据和向量本身。

【讨论】:

@user4815162342 返回必须是vector * :( @keltar 你能举例说明通过分配动态内存后代码的样子吗? 我想我们越来越近了,但我收到了一个编译错误:eda.c:16: error: invalid conversion from ‘void*’ to ‘vector*’ eda.c:17: error: invalid conversion from ‘void*’ to ‘float*’ 我们可以做些什么来让它工作? @Gerard 它是什么编译器?您是否手动强制 C++ 模式?在 C 中,不允许编译器抱怨从 void* 转换为任何其他指针类型。然而,在 C++ 中,他们必须抱怨。因此,如果您出于某种原因处于 C++ 模式,则需要将 malloc 的返回值转换为您想要的类型(例如 vector *newvect = (vector*)malloc(sizeof(*newvect));,float* 也是如此)。然而,对 C 代码强制使用 C++ 模式是很奇怪的。 我们需要用C编写代码并用g++编译...我的大学教授应该很特别...无论如何,现在可以正常工作了!非常感谢:D【参考方案2】:

在这一行

printf("%f\n", v[i]->data[1]); //segmentation fault:11 :(!! 

i 等于 n。由于v 被声明为v[n],上述行通过越界访问v 引发了未定义的行为。


要解决将地址返回到局部变量的问题,请执行以下操作:

vector * create_vector(size_t n, float * comps)

  vector * newvect = malloc(sizeof(*newvect);
  if (NULL != newvect)
  
    return NULL;
  

  newvect->data =  malloc(n * sizeof(*newvect->data));
  if (NULL != newvect->data)
  
    free(newvect);
    return NULL;
  

  for(size_t i = 0; i < n; i++) 
  
    newvect->data[i] = comps[i];
    printf("newvect->data[%zu] = %.1f\n", i, newvect->data[i]);
  

  newvect->size = n;

  return newvect;

【讨论】:

但是如果例如i = 0,我尝试访问v [0],这些值是在限制范围内的......为什么还是会出错? @Gerard:对于有问题的那一行(根据我的回答,for 循环之后的那一行)i 永远不会是0 如果我尝试在循环外运行没有变量“i”的行,如下所示:printf("%f\n", v[0]-&gt;data[1]); //(outside the loop) 问题仍然存在......我认为问题是 keltar 在上一个答案中所说的,但我不明白他所说的“通过为 newvect 分配动态内存”是什么意思 @Gerard:您的代码中至少有两个问题:keltar 描述的一个和我提到的一个。

以上是关于分段错误:循环打印时为 11的主要内容,如果未能解决你的问题,请参考以下文章

带有 std::promise 的 C++11 分段错误

在指针迭代中使用 for 循环时出现分段错误

分段错误(核心转储) - 无法访问的计数器值

分段错误:在 C++ 中弹出向量时出现 11

循环C ++中的分段错误Openmp

如何在我的 do-while 循环中解决此分段错误?