0

I have a struct:

typedef struct{
        int *issueTypeCount;
    }issueTypeTracker;

I've declared a variable of type issueTypeTracker:

issueTypeTracker *typeTracker;

I've allocated necessary memory:

typeTracker = (issueTypeTracker*) malloc(sizeof(issueTypeTracker) * issueTypeList.count());
typeTracker->issueTypeCount = (int*) calloc(65536,sizeof(int));

And then when I try to do something with it, I get a segmentation fault

while(qry.next()){ //while there are records in the query
        for(j=0;j<locationList.count();j++){ // no problem
            if(qry.value(1) == locationList[j]){ //no problem
                for(i=0;i<issueTypeList.count();i++){ //no problem
                    typeTracker[j].issueTypeCount[i]++; //seg fault as soon as we hit this line
                }
            }
        }
    }

I figured it would be a problem with the way i've allocated memory, but as far as I'm aware i've done it correctly. I've tried the solutions proposed in this question, however it still did not work.

I've tried replacing typeTracker->issueTypeCount = (int*) calloc(65536,sizeof(int)); with:

for(j=0;j<issueTypeList.count();j++){
        typeTracker[j].issueTypeCount = (int*) calloc(65536,sizeof(int));
    }

But I still get the same issue. This happens with any value of j or i, even zero.

This is a lot more trouble than it's worth and a poor implementation of what I'm trying to do anyway, so I'm probably going to scrap this entire thing and just use a multidimensional array. Even so, I'd like to know why this doesn't work, so in the future I don't have trouble when i'm faced with a similar scenario.

Community
  • 1
  • 1
ozzymado
  • 960
  • 3
  • 15
  • 26
  • 1
    Check the return value of malloc/calloc. – bitmask Jun 13 '14 at 16:10
  • @bitmask I ran it through the debugger again - as expected, `typeTracker`'s value is a memory address (different from the one it starts with so I know malloc worked) and `typeTracker.issueTypeCount`'s value is zero. – ozzymado Jun 13 '14 at 16:14
  • 1
    Any reason it's not just a `std::vector` and a `std::vector`? – chris Jun 13 '14 at 16:23
  • @chris That's what I'm going to do now because this isn't a very good solution to requiring a multidimensional array, but this is still an interesting problem I'd like to solve. – ozzymado Jun 13 '14 at 16:25
  • 1
    @Lighthat: There you have your answer :) --- If `typeTracker.issueTypeCount` is the `nullptr` then this means `calloc` refused to answer your request for memory (for whatever reason I do not dare to speculate). Naturally, accessing this means accessing memory that doesn't belong to you. Hence a segfault. – bitmask Jun 13 '14 at 16:25
  • @bitmask Aren't those expected results? Other arrays I initialize with `calloc` end up having a value of zero as well when I use the debugger and they work just fine. And when I use `malloc` it doesn't put any values. How would I go about solving that? – ozzymado Jun 13 '14 at 16:27
  • @Lighthat, That's the unfortunate thing about undefined behaviour (assuming by zero you mean the pointer and not the values of the elements). – chris Jun 13 '14 at 16:29
  • 2
    You allocate an array of `issueTypeTracker` (with `malloc`) then you only initialize the first element (with `calloc`). – Adam Jun 13 '14 at 16:29
  • More importantly, your `typeTracker` array is allocated as length `issueTypeList.count()` but accessed as if it was of length `locationList.count()`. – Adam Jun 13 '14 at 16:30
  • @chris I mean the elements (i'm fairly certain, at least). I have this line: `timeTracker = (double*) calloc(65536,sizeof(double));` for another array and when I look at its value in the debugger, it is zero. When I try to access the data in `timeTracker`, it works fine. – ozzymado Jun 13 '14 at 16:31
  • Since you tagged this as `c++` and not `c` then @chris has the right answer. Use the C++ mechanisms for this. You're just writing C code and calling it C++. – Adam Jun 13 '14 at 16:31
  • @Adam I've already mentioned I've done something else to solve the problem because this isn't a good solution, I want to find out why this is happening regardless. WRT the issue of different lengths, I know, this is why I allocate excess memory anyway. Neither `locationList.count()` or `issueTypeList.count()` will ever be more than a couple thousand. Additionally if I'm only initializing the first element with calloc, how come I get the same issue with the `for` loop approach? – ozzymado Jun 13 '14 at 16:33
  • It doesn't matter if the length is more or less than a couple thousand, it matters whether or not it's long enough. If `locationList.count()` > `issueTypeList.count()` then there will be a problem. But you're saying that this happens for `j == i == 0`, which means the first iterations of the loop, therefore it looks like there is a problem in the code between the allocation and that loop. (frankly I think you should remove your non-loop allocation. It's so obviously wrong that it's the first thing any new reader of this question gravitates to). – Adam Jun 13 '14 at 17:36
  • Oh, for your "excess" you mean that your `issueTypeCount` arrays are always long enough because the assumption `issueTypeList.count() < 65536` always holds? If you can guarantee that then that's fine (though wasteful and poor coding), but I'm talking about the length of `typeTracker`. You allocate using one length and iterate over it with another (using `j`). – Adam Jun 13 '14 at 17:39

1 Answers1

1

You have several issues. Firstly, you're not checking your allocations for success, so any of your pointers could be NULL/nullptr.

Secondly,

typeTracker->issueTypeCount = (int*) calloc(65536,sizeof(int));

is equivalent to

typeTracker[0].issueTypeCount = (int*) calloc(65536,sizeof(int));

so, you initialized the issueTypeCount member for only the first issueTypeTracker in your array. For the other issueTypeList.count() - 1 elements in the array, the pointer is uninitialized.

Therefore this line:

typeTracker[j].issueTypeCount[i]++; //seg fault as soon as we hit this line

will invoke UB for any j>0. Obviously if your allocation failed, you have UB for j==0 as well.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • For the first issue, I'm fairly certain that the allocations are succeeding because i'm getting memory addresses where I expect them and zero values where I expect them (the actual data contained in the array). Either way you are correct and it's an easy fix. For the second issue, I caught that too and that's why I used the `for` loop approach, but I still get the segmentation fault for any value of `i` or `j`. – ozzymado Jun 13 '14 at 16:47
  • Don't be _fairly certain_, just code it correctly so it can't be wrong. Check the return value and bail out if an allocation fails. When the process cores, what was the address it was trying to de-reference? What were the values of `i` and `j`? If you still can't see how you got to that point, run under valgrind and see if something else is damaging your array. – Useless Jun 13 '14 at 16:53
  • The values of `i` and `j` are within bounds of both arrays. The address being dereferenced is not `0x0`, it's a valid memory address. I am using the Qt debugger and nothing seems out of the ordinary at all, which is why this problem stumps me. I know I should check the return values of the memory allocation in the program, but right now I am using the debugger and the memory is being allocated properly in this instance...except, apparently not, since I'm getting a segfault. I am certain I'm not accessing a null pointer. – ozzymado Jun 13 '14 at 16:57