1

I get a segmentation fault when my function reads floats from a string and places them in a void array. The segfault occurs after about 200 iterations of the for loop in the following code:

// Allocate memory
void** data;
data = (void**)malloc(num_vals * sizeof(float));

// Convert text to floats
(*(float**)data)[0] = atof(strtok(text, " "));  
for(int index=1; index<num_vals; index++) {
    (*(float**)data)[index] = atof(strtok(NULL, " "));   
    std::cout << (*(float**)data)[index] << std::endl;
}

The void array is necessary because the size and type of data in the string are determined at run-time. I've tried increasing the malloc size, but it doesn't change anything. Any thoughts?

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
MatthewScarpino
  • 5,672
  • 5
  • 33
  • 47

6 Answers6

5

Seriously??

std::vector<float> data;
std::istringstream str(text);
float fv;
while (str >> fv)
{
  data.push_back(fv);
}

Now that's c++

Nim
  • 33,299
  • 2
  • 62
  • 101
  • while this is clearly a better solution it doesn't explain the where the seg fault is or why it occurs in the op's code. – Kevin Sep 08 '11 at 14:02
  • @Kevin, if the OP finds the answer unacceptable, it's his choice - I prefer to tackle the underlying problem (approach) rather than the specific issue here (which is an all too real side-effect of the approach) – Nim Sep 08 '11 at 14:27
  • I wish I could do that, but as I said, I don't know the data type of the string content or size until run-time. Still, I need to keep the data in a common structure, so I'm stuck with void pointers. – MatthewScarpino Sep 08 '11 at 15:01
2

As much as it pains me to do so, here is a version of your code that probably does what you want.

// Allocate memory
void* data;
data = malloc(num_vals * sizeof(float));

// Convert text to floats
((float*)data)[0] = atof(strtok(text, " "));  
for(int index=1; index<num_vals; index++) {
    ((float*)data)[index] = atof(strtok(NULL, " "));   
    std::cout << ((float*)data)[index] << '\n';
}

Note, however, that if you worked for me and tried to check in that code, we would have a serious discussion about your choice of career.

I'd rather see something like this:

std::vector<float> v;
std::copy(std::istream_iterator<float>(std::istringstream(text)),
          std::istream_iterator<float>(),
          std::back_inserter(v));

P.s. Rob's rule #47: Never say std::endl when you mean '\n'.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • I like your last few lines, but I think it's a little ambitious for the OP given the current implementation... ;) – Nim Sep 08 '11 at 14:19
  • It has to be a void** because I'm allocating the memory in a function and freeing it elsewhere. If vectors were a possibility, I would certainly use them. – MatthewScarpino Sep 08 '11 at 15:03
  • @user, from your usage, you really want `void*`, not `void**`. If you have a requirement specifically for pointer-to-pointer-to-void instead of pointer-to-void, please add that to the question. – Robᵩ Sep 08 '11 at 15:51
1

Why do you convert to void ** ??? You code contains couple errors on indexing, so let me show some reasonable changes

float* data;
data = (float*)malloc(num_vals * sizeof(float));

// Convert text to floats
data[0] = atof(strtok(text, " "));  
for(int index=1; index<num_vals; index++) {
 data[index] = atof(strtok(NULL, " "));   
 std::cout << data[index] << std::endl;
}
Dewfy
  • 23,277
  • 13
  • 73
  • 121
1

You got your types mixed up in your inexplicable attempt to create this monster under the pretence of writing "C++". Anyway. what you're mallocing is nothing but a float*, so you need to cast data back to float*:

((float*)data)[0] = myfloat;
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

I think, since you are defining a pointer of void pointer and allocating/casting it to pointer of void pointer, it allocates 4 byte memory for each element because in C/C++, regardles of the type of the pointer, pointers are always 4 bytes which are not big enough floats.

reader_1000
  • 2,473
  • 17
  • 15
0

There're several issues. One is - data should be void *, you have redundant *. Other might be alignment, i'm not sure you are able to place a float in any location in the memory.

Drakosha
  • 11,925
  • 4
  • 39
  • 52