I'm trying to create a self-expanding array of a structure. I saw the questions here, here and here but the answers didn't seem to apply to my situation.
I have had pretty good luck using this technique using an array of strings, but using a structure doesn't work. Below is the code:
// SO1.h
//
#pragma once
typedef struct {
int tag;
int type;
}structure;
void addElement(structure* Tkn_A, const int Tag);
void listArray();
Here is the C code.
// SO1.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "stdio.h"
#include "malloc.h"
#include "SO1.h"
const int ARRAY_INITIAL_SIZE = 2;
const int ARRAY_ADDITIONAL_SIZE = ARRAY_INITIAL_SIZE / 2;
structure* userArray;
size_t userArrayLength = -1;
size_t userArrayAvailable = ARRAY_INITIAL_SIZE;
int main()
{
userArray = (structure*)malloc(userArrayAvailable * sizeof(structure));
printf(" orgarrptr=%p\n", userArray);
addElement(userArray, 13);
addElement(userArray, 14);
addElement(userArray, 15);
addElement(userArray, 16);
addElement(userArray, 17);
addElement(userArray, 18);
addElement(userArray, 19);
addElement(userArray, 20);
addElement(userArray, 21);
addElement(userArray, 22);
addElement(userArray, 23);
addElement(userArray, 24);
addElement(userArray, 25);
}
void addElement(structure* userArray, const int tag)
{
userArrayLength++;
if (userArrayLength > userArrayAvailable) {
userArrayAvailable += ARRAY_ADDITIONAL_SIZE;
structure* originalUserArrayPtr = userArray;
printf(" orgarrptr=%p\n", originalUserArrayPtr);
userArray = (structure*)realloc(userArray, userArrayAvailable * sizeof(structure));
printf(" newarrptr=%p\n", userArray);
if (originalUserArrayPtr != userArray) {
printf("pointers different\n");
}
}
userArray[userArrayLength].tag = tag;
userArray[userArrayLength].type = 1;
printf("%2d %d\n\n", userArray[userArrayLength].tag,
userArray[userArrayLength].type);
listArray();
}
void listArray()
{
for (size_t i = 0; i <= userArrayLength; i++) {
printf("%2d %d\n", userArray[i].tag,
userArray[i].type);
}
}
When the program doesn't complete normally, I get the following error on the line doing the realloc:
Debug Assertion Failed!
File: minkernel\crts\ucrt\src\appcrt\heap.cpp
Line: 604
Expression _CrtIsValidHeapPointer(block)
This happens when the realloc comes up with a different pointer than the original with a new length. But the next time I look at the pointer, it still has the value of the old pointer. Below is the output of one run:
:
:
:
13 1
14 1
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
20 1
orgarrptr=015C79E0
newarrptr=015C79E0
21 1
13 1
14 1
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
21 1
orgarrptr=015C79E0
newarrptr=015C5F58 <=== new pointer
pointers different
22 1
13 1
14 1
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
-842150451 -842150451
21 1
-1863261150 134281082
orgarrptr=015C79E0 <=== original pointer
exited with code 3.
Does anyone know what would cause this problem? TIA.
Sorry for the long question, but I wanted to give out all the details. I don't think Visual Studio has anything to do with problems, but don't know for sure. I'm using VS Community Edition 2019, 16.1.3.
Update: Originally I had two problems. One getting the pointer updated and the other getting garbage data. I decided to split the two into two different questions.
void addElement(structure* userArray, const int tag)works inside on the local variableuserArraybut no on the global variableuserArrayas you might expect. (The latter is eclipsed by the former inside the function.) Hence, wheneverrealloc()returns a new address, it gets lost as soon as you leave the function while the globaluserArrayis kept unchanged. You could eliminate parameteruserArrayfromaddElement(). However, I would recommend toreturn userArray(changing the return type tostructure*) and assign result ofaddElement()to the global again.addElementto manage different allocations of the structurestructure, it's better to manage the element counter (userArrayLength) in an other way. In the actual way you may manage only one array because the counter is managed using only one variable (userArrayLength). A simple way should be to pass the counter pointer to theaddElementand the to thelistElementfunctions.realloc()but more with scopes and eclipsing. Respect. ;-)