I've just re-start learning C, but i'm really confused with some memory management details.
I'm getting
pointer being freed was not allocated ... Abort trap
for the code below. Do i really need 1 free per malloc? Why my code is wrong?
Thanks!
#define N 9
typedef struct
{
int MAX_LIST_SIZE;
int length;
int *ini;
}List;
/* allocates new List and its data */
List *newList(int size)
{
List *list = malloc(sizeof(List));
list->MAX_LIST_SIZE = size;
list->length = 0;
list->ini = malloc(sizeof(int) * size);
return list;
}
/* add some value to the list */
void addList(List *list, int val)
{
if (list->length < list->MAX_LIST_SIZE)
list->ini[list->length++] = val;
else
fprintf(stderr, "Error: add(): List is full.\n");
}
/* get an array of N*N lists malloc-ed Lists */
List *gridList()
{
int i, j;
List *cells = malloc(sizeof(List) * N * N);
for (i = 0; i < N * N; i++)
{
/* malloc is called inside NewList()*/
cells[i] = *newList(N);
for (j = 0; j < N; j++)
addList(&cells[i], j + 1);
}
return cells;
}
/* inside main */
List *cells = gridList();
/* use cells ... */
/* free */
for (i = 0; i < N * N; i++)
{
free(cells[i].ini);
/* line below causes CRASH */
free(&cells[i]);
}
You do :
cells[i] = *newList(N);
which sets each element in cells to a copy of the list dynamically allocated by newList. So newList dynamically allocates a list, then you take the pointer to that dynamically allocated List, dereference it, and copy it into cells[i]. So then later on when you go to free() each element:
free(&cells[i]);
It doesn't work because each element in cells[i] is a List, not a List * (list pointer) allocated by malloc().
So you have two options. One (bad one) is to just remove that last free() line since there's nothing to free. However, this just covers up a larger problem which is that you now have memory leaks because you can't go back and free the dynamically allocated Lists created with newList().
Instead it's likely you want to have an array of pointers to the lists, which you can do by changing it to:
List **cells = malloc(sizeof(List*) * N * N);
so that cells[i] refers to a List *. newList() returns such a pointer, so you would change that line to:
cells[i] = newList(N);
similarly, addList() takes such a pointer, so you'd simply change that line to:
addList(cells[i], j + 1);
since &cells[i] would pass it the address of the pointer, which is not what you want.
Finally, change the free statements to:
free(cells[i]->ini); // ->init because cells[i] is now a pointer to a List, List *
free(cells[i]);
The problem is you are allocating an array of lists, copying the full contents of your lists into the array elements, and then trying to free them. The original allocated List records are a memory leak, and the free calls are indeed trying to free memory that was not malloc'ed (or more exactly were malloc'ed in a single big block).
You want an array of pointers to pointers to hold your lists:
/* get an array of N*N lists malloc-ed Lists */
List **gridList()
{
int i, j;
// VV note change here
List **cells = malloc(sizeof(List*) * N * N);
for (i = 0; i < N * N; i++)
{
/* malloc is called inside NewList()*/
cells[i] = newList(N); // << Note change here.
for (j = 0; j < N; j++)
addList(cells[i], j + 1);
}
return cells;
}
/* free */
for (i = 0; i < N * N; i++)
{
free(cells[i]->ini); // << and here
/* line below causes CRASH */
free(cells[i]); // << and here
}
free(cells);
Related
I pasted code at the bottom that allocates lots of pointers but doesn't free any. I have a struct named Node that has fields of type struct Node**. In my main function I have the variable: Node** nodes = malloc(size * typeof(Node*));. I would like to know how to properly deallocate nodes.
typedef struct Node {
size_t id; // identifier of the node
int data; // actual data
size_t num_parents; // actual number of parent nodes
size_t size_parents; // current maximum capacity of array of parent nodes
struct Node** parents; // all nodes that connect from "upstream"
size_t num_children; // actual number of child nodes
size_t size_children; // current maximum capacity of array of children nodes
struct Node** children; // all nodes that connect "downstream"
} Node;
I've pasted the whole code down at the bottom because it is already almost minimal (only things we don't need here are the printing function and find_smallest_value function). VS2019 also gives me two warnings for two lines within the main loop in the main function where I'm allocating each node:
Node** nodes = malloc((num_nodes + 1) * sizeof(Node*));
for (size_t i = 1; i <= num_nodes; i++) {
nodes[i] = malloc(sizeof(Node)); // WARNING Buffer overrun while writing to 'nodes': the writable size is '((num_nodes+1))*sizeof(Node *)' bytes, but '16' bytes might be written.
nodes[i]->id = i; // WARNING Reading invalid data from 'nodes': the readable size is '((num_nodes+1))*sizeof(Node *)' bytes, but '16' bytes may be read.
I don't understand these warnings at all. Finally, you can obtain large input for this program from this website. Just save it to a text file and modify the hardcoded file name in the main function. The program runs fine if I comment out the last lines where I try to deallocate my nodes. My attempt at deallocating crashes the program. I'd greatly appreciate if anyone could explain the correct way to do it.
Explaining the purpose of the code:
The code at the bottom has the following goal. I'm trying to build a directed graph where every vertex has a label and a value. An example of such a graph. The graphs I'm interested in all represent hierarchies. I am to perform two operations on these graphs: I. given a vertex, find the one with smallest value that above it in the hierarchy and print its value; II. given a pair of vertices, swap their places. For example, given vertices 4 and 2 in that figure, the result of operation II would be the same graph but the vertices labelled 2 and 4 would have their labels and data swapped. Given vertex 6, the result of operation I would be "18". I implemented both operations successfully, I believe.
My main function reads from a txt file in order to build the data structure, which I chose to be a multiply linked list. Any input file should be of the following format (this file generates the graph shown in the figure and performs some operations on it):
7 8 9
21 33 33 18 42 22 26
1 2
1 3
2 5
3 5
3 6
4 6
4 7
6 7
P 7
T 4 2
P 7
P 5
T 1 4
P 7
T 4 7
P 2
P 6
First line has three numbers: number of vertices (nodes), number of edges (k, connections) and number of instructions (l, either operation I or II).
Second line is the data in each node. Labels correspond to the index of the node.
The next k lines consist of two node labels: left is a parent node, right is a child node.
The next l lines consist of instructions. P stands for operation I and it's followed by the label of the node. T stands for operation II and it's followed by the two labels of the nodes to be swapped.
The entire pattern can repeat.
The code:
#include<stdlib.h>
#include<stdio.h>
typedef unsigned int uint;
typedef struct Node {
size_t id; // identifier of the node
int data; // actual data
size_t num_parents; // actual number of parent nodes
size_t size_parents; // current maximum capacity of array of parent nodes
struct Node** parents; // all nodes that connect from "upstream"
size_t num_children; // actual number of child nodes
size_t size_children; // current maximum capacity of array of children nodes
struct Node** children; // all nodes that connect "downstream"
} Node;
Node** reallocate_node_array(Node** array, size_t* size) {
Node** new_array = realloc(array, sizeof(Node*) * (*size) * 2);
if (new_array == NULL) {
perror("realloc");
exit(1);
}
*size *= 2;
return new_array;
}
// The intention is to pass `num_children` or `num_parents` as `size` in order to decrease them
void remove_node(Node** array, size_t* size, size_t index) {
for (size_t i = index; i < *size - 1; i++) {
array[i] = array[i + 1];
}
(*size)--; // the decrement to either `num_children` or `num_parents`
}
void remove_parent(Node* node, size_t id) {
for (size_t i = 0; i < node->num_parents; i++) {
if (node->parents[i]->id == id) {
remove_node(node->parents, &node->num_parents, i);
}
}
}
void remove_child(Node* node, size_t id) {
for (size_t i = 0; i < node->num_children; i++) {
if (node->children[i]->id == id) {
remove_node(node->children, &node->num_children, i);
}
}
}
void add_parent(Node* node, Node* parent) {
if (node->num_parents >= node->size_parents) {
node->parents = reallocate_node_array(node->parents, &node->size_parents);
}
node->parents[node->num_parents++] = parent;
}
void add_child(Node* node, Node* child) {
if (node->num_children >= node->size_children) {
node->children = reallocate_node_array(node->children, &node->size_children);
}
node->children[node->num_children++] = child;
}
uint number_of_digits(int n) {
uint d = 0;
do { d++; n /= 10; } while (n != 0);
return d;
}
// return format: "{ parent1.id parent2.id ...} { id data } { child1.id child2.id ...}"
void print_node(Node node) {
printf("{ ");
for (size_t i = 0; i < node.num_parents; i++) {
printf("%zu ", node.parents[i]->id);
}
printf("} [ %zu %d ] { ", node.id, node.data);
for (size_t i = 0; i < node.num_children; i++) {
printf("%zu ", node.children[i]->id);
}
printf("}\n");
}
void switch_nodes(Node* n1, Node* n2, Node** array) {
uint temp_id = n1->id;
uint temp_data = n1->data;
n1->id = n2->id;
n1->data = n2->data;
n2->id = temp_id;
n2->data = temp_data;
Node* temp = array[n1->id];
array[n1->id] = array[n2->id];
array[n2->id] = temp;
}
int find_smallest_valued_parent(Node* node, uint depth) {
// has no parents
if (node->num_parents == 0 || node->parents == NULL) {
if (depth == 0) return -1; // there was no parent on first call (nothing to report)
else return node->data;
}
else {
depth++;
int minimum_value = node->parents[0]->data; // we're guaranteed 1 parent
for (size_t i = 0; i < node->num_parents; i++) {
int next_value = find_smallest_valued_parent(node->parents[i], depth);
if (node->parents[i]->data < next_value) next_value = node->parents[i]->data;
if (next_value < minimum_value) minimum_value = next_value;
}
return minimum_value;
}
}
void free_node_array(Node** array, size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
free(array[i]);
}
free(array);
}
int main() {
char* file_name = "input_feodorv.txt";
FILE* data_file = fopen(file_name, "r");
if (data_file == NULL) {
printf("Error: invalid file %s", file_name);
return 1;
}
for (;;) {
size_t num_nodes, num_relationships, num_instructions;
if (fscanf(data_file, "%zu %zu %zu\n", &num_nodes, &num_relationships, &num_instructions) == EOF)
break;
Node** nodes = malloc((num_nodes + 1) * sizeof(Node*));
for (size_t i = 1; i <= num_nodes; i++) {
nodes[i] = malloc(sizeof(Node)); // WARNING Buffer overrun while writing to 'nodes': the writable size is '((num_nodes+1))*sizeof(Node *)' bytes, but '16' bytes might be written.
nodes[i]->id = i; // WARNING Reading invalid data from 'nodes': the readable size is '((num_nodes+1))*sizeof(Node *)' bytes, but '16' bytes may be read.
fscanf(data_file, "%u ", &nodes[i]->data);
nodes[i]->num_children = 0;
nodes[i]->size_children = 2;
nodes[i]->children = (Node**)malloc(2 * sizeof(Node*));
for (size_t j = 0; j < 2; j++) nodes[i]->children[j] = malloc(sizeof(Node));
nodes[i]->num_parents = 0;
nodes[i]->size_parents = 2;
nodes[i]->parents = (Node**)malloc(2 * sizeof(Node*));
for (size_t j = 0; j < 2; j++) nodes[i]->parents[j] = malloc(sizeof(Node));
}
for (size_t i = 0; i < num_relationships; i++) {
size_t parent_id, child_id;
fscanf(data_file, "%zu %zu\n", &parent_id, &child_id);
add_child(nodes[parent_id], nodes[child_id]);
add_parent(nodes[child_id], nodes[parent_id]);
}
for (size_t i = 0; i < num_instructions; i++) {
char instruction;
fscanf(data_file, "%c ", &instruction);
if (instruction == 'P') {
size_t id;
fscanf(data_file, "%zu\n", &id);
int minimum_value = find_smallest_valued_parent(nodes[id], 0);
if (minimum_value == -1) printf("*\n");
else printf("%u\n", minimum_value);
}
else {
size_t n1_id, n2_id;
fscanf(data_file, "%zu %zu\n", &n1_id, &n2_id);
switch_nodes(nodes[n1_id], nodes[n2_id], nodes);
}
}
/**/
for (size_t i = 1; i <= num_nodes; i++) {
free_node_array(nodes[i]->parents, 0, nodes[i]->size_parents);
free_node_array(nodes[i]->children, 0, nodes[i]->size_children);
}
free_node_array(nodes, 0, num_nodes);
/**/
}
}
There is a memory leak in your code. In the main() function, you are doing:
nodes[i]->children = (Node**)malloc(2 * sizeof(Node*));
for (size_t j = 0; j < 2; j++) nodes[i]->children[j] = malloc(sizeof(Node));
and
nodes[i]->parents = (Node**)malloc(2 * sizeof(Node*));
for (size_t j = 0; j < 2; j++) nodes[i]->parents[j] = malloc(sizeof(Node));
that mean, allocating memory to nodes[i]->children[j] and nodes[i]->parents[j] pointers.
In add_child() and add_parent() function, you are making them point to some other node resulting in loosing there allocated memory reference:
void add_parent(Node* node, Node* parent) {
.....
node->parents[node->num_parents++] = parent;
}
void add_child(Node* node, Node* child) {
.....
node->children[node->num_children++] = child;
}
You actually don't need to allocate memory to nodes[i]->children[j] and nodes[i]->parents[j] pointers in main() because these pointer are suppose to point to the existing nodes of the graph and you are already allocating memory to those nodes here in main():
nodes[i] = malloc(sizeof(Node));
nodes[i] is an element of array of all the nodes of the given graph and childrens and parents pointer should point to these nodes only.
Now coming to freeing these pointers:
The way you are freeing the nodes of graph is not correct. Look at free_node_array() function:
void free_node_array(Node** array, size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
free(array[i]);
}
free(array);
}
and you are calling it in this way:
for (size_t i = 1; i <= num_nodes; i++) {
free_node_array(nodes[i]->parents, 0, nodes[i]->size_parents);
free_node_array(nodes[i]->children, 0, nodes[i]->size_children);
}
That mean, you are freeing the pointers pointed by array of pointers nodes[i]->parents and nodes[i]->children. The members of nodes[i]->parents and nodes[i]->children are pointers which are pointing to elements of nodes array. It is perfectly possible that a node can be a child 1 or more parents and a parent node can have more than 1 child. Now assume case where a child node is pointed by 2 parent nodes, say n1 and n2. When you call free_node_array() function and pass the first parent (n1), it will end you freeing that child node and when free_node_array() function is called to free the second parent (n2), it will try to free the node which is already freed while freeing n1.
So, this way of freeing the memory is not correct. The correct way to free the memory is, simply, free the elements of nodes array because it's the array which will contain all the nodes of given graph and parents and children pointers are supposed to point to these nodes only. No need to traverse the hierarchy of parent and child nodes. To free the graph appropriately, you should do:
Traverse through the nodes array and for each element of array:
Free the array of parents pointer (free (nodes[i]->parents).
Free the array of children pointer (free (nodes[i]->children).
Free that element of nodes array (free (nodes[i]).
Once, this is done then free the nodes array - free (nodes).
I am working on a project that I have made use of Calloc and I am trying to free the memory at the end of my main{} function. However, after the program finishes running and I click on the stop, I get this "proj.exe has triggered a breakpoint."
at this set of codes:
while (freeSpace != NULL) {
free(freeSpace++);
}
Here are my codes for allocating memory:
scanf("%d", &SEG);
BLOCKS = 128 / SEG;
for (int k = 0; k < BLOCKS; k++)
{
memory = (int *)calloc(BLOCKS, sizeof(int));
// handle memory allocation failure
}
for (int i = 0; i < BLOCKS; i++)
{
memory[i] = (int *)calloc(SEG, sizeof(int));
// handle memory allocation failure
}
for (int l = 0; l < BLOCKS+5; l++)
{
//freeSpace = (int*)malloc(l * sizeof(int));
freeSpace = (int *)calloc( BLOCKS + 5, sizeof(int));
// handle memory allocation failure
}
for (int o = 0; o < BLOCKS; o++)
{
memorySpace = (int *)calloc(BLOCKS, sizeof(int));
// handle memory allocation failure
}
`
This is the part where I free my memory:
while (freeSpace != NULL) {
free(freeSpace++);
}
Can someone please assist me?
Its really hard to fix your issue because it seems like that these are only a part of your code or it is a prototype?
The following code only based on some 'guess':
int main()
{
scanf("%d", &SEG);
BLOCKS = 128 / SEG;
int* memory = (int *)calloc(BLOCKS+1, sizeof(int*)); // the last is a 'NULL' pointer
memset(memory, 0, sizeof(int*)*BLOCKS+1);
for (int i = 0; i < BLOCKS; i++)
{
memory[i] = (int *)calloc(SEG, sizeof(int));
// handle memory allocation failure
}
while (memory != NULL) {
free(memory++);
}
}
I think you are misunderstanding how pointers work when allocating arrays. Your very first loop has a memory leak in it because you are changing what I am assuming the "memory" pointer is pointing to.
To allocate an array in C would be like below.
int *bigspace;
bigspace = malloc(20 * sizeof(int));
Here we made the pointer "bigspace" point to a new chunk of memory 20 times the size of an integer which is an array. If you did something like below..
int *bigspace;
bigspace = malloc(20 * sizeof(int));
bigspace = malloc(20 * sizeof(int));
This would be no bueno. We are first making "bigspace" pointer point to a chunk of memory (array of ints) and then we are changing what "bigspace" is pointing to by making it point to a new chunk of memory. This means your first chunk of memory does not have a pointer to it anymore and that memory is leaked!
I think the problem is that the value of freeSpace++ is garbage at the end of your allocated memory.
Free a garbage pointer causes the problem.
Unable to find where the memory leak is happening in this code.
Basically I want to write a XS wrapper for a C-function which returns a two-dimensional array.
C-function:
int CW_returnArray(double** arrayDouble, int* count)
{
int number = 10;
int index, index1;
for(index = 0; index < number; index++)
{
for(index1 = 0; index1 < 10000; index1++)
{
arrayDouble[index][index1] = 12.51;
}
count[index] = 10000;
}
return number;
}
array -> output param to hold the two dimensional array
count -> output param to hold the number of element in each 1D array
XS wrapper:
void
returnArray()
PPCODE:
{
/** variable declaration **/
double** array;
int i = 0, j=0, status;
int* count;
int totalArrays;
SV** SVArrays; // to hold the references of 1D arrays
SV** SVtempArray; // temporary array to hold the elements of 1D array
/** allocate memory for C-type variables **/
New(0, array, 10, double*);
for(i = 0; i<10;i++)
{
New(0, array[i], 10000, double);
}
New(0, count, 10, int);
/** call C function **/
status = CW_returnArray(array, count);
/** check the status and retrieve the array to store it in stack **/
if(status > 0)
{
totalArrays = status;
New(0, SVArrays, totalArrays, SV*);
for(i = 0; i<totalArrays; i++)
{
/** allocate memory for temporary SV array **/
New(0, SVtempArray, count[i], SV*);
for(j = 0; j<count[i]; j++)
{
SVtempArray[j] = newSVnv(array[i][j]);
}
/** Make an array (AV) out of temporary SV array and store the reference in SVArrays **/
SVArrays[i] = newRV_noinc((SV*) av_make(count[i], SVtempArray));
/** free the memory allocated for temp SV array **/
for(j = 0; j<count[i]; j++)
{
sv_free(SVtempArray[j]);
}
Safefree(SVtempArray); SVtempArray = NULL;
}
}
else
{
totalArrays = 0;
}
/** push the return values to stack **/
EXTEND(SP, 2);
PUSHs(sv_2mortal(newSViv(status)));
PUSHs(sv_2mortal(newRV_noinc((SV*) av_make(totalArrays, SVArrays))));
/** clean up allocated memory for SV "array of array" , if needed **/
if(totalArrays > 0)
{
Safefree(SVArrays); SVArrays = NULL;
}
/** clean up allocated memory for C-type variables **/
for(i = 0; i<10;i++)
{
Safefree(array[i]);
}
Safefree(array); array = NULL;
Safefree(count); count = NULL;
}
An "array of array" is returned from XS.
testing in Perl script:
for(1..100)
{
my ($status, $arrayref) = returnArray();
undef $status;
$arrayref = [];
system('pause');
}
Every time the function returnArray() is called, the Commit size of Perl process is increasing.
But I would expect that the $arrayref variable should be garbage collected every time and the Memory usage should not increase.
I hope, I am freeing all the allocated memory in XS. But still there is a memory leak.
What is wrong with this XS code for memory leak?
Well, the pattern of "create a template array, do av_make(), then free the template" is not very good -- you'd be much better by simply creating your array with newAV(), av_extend()ing it to the right size, and then doing av_store(newSVnv(...)) for each element. That lets you avoid the intermediate SVtempArray allocations entirely.
However, that's not what you asked about. I think your problem is that you Safefree(SVArrays) without first sv_free()ing each element. Since av_make() duplicates the contents of the source array, AFAICT you're leaking the reference created by
SVArrays[i] = newRV_noinc((SV*) av_make(count[i], SVtempArray));
You'll need to iterate over SVArrays and call sv_free() on each element before you Safefree(SVArrays).
I have:
uint64_t *list;
if((list = malloc(10 * sizeof(uint64_t))) == NULL){
errx(1, "malloc");
}
I need to populate this array, increment the address of it.
I mean:
(*list)++;
list = 1;
(*list)++;
list = 2;
(*list)++;
list = 3;
(*list)++;
list = 4;
How do I do that?
You can use the allocated memory like a normal array:
list[0] = 1;
list[1] = 2;
/* etc. */
Edit:
What you are doing is increase the first entry in the "array" which probably contains a value you don't expect, then you reassign the pointer so it no longer points to your allocated memory, and so on. Also, if you really want to "increment the address" of the allocated memory, it's just simple as list++, however this is also changing the pointer so you loose the original allocated address and can not free it later (unless you save it.)
you can use a loop
for(int i = 0; i < 10; i++) {
list[i] = i+1;
}
I have a pointer to a struct list* ptr
The struct contains a char and a pointer to the next struct and these are used for an array of structures like so:
list array[setSize]; //setSize is defined as 20
Without using malloc, I need to initialize list* ptr so that it has all the elements of the array.
I have tried the following and I get a segmentation fault. I believe I am utterly misunderstanding how pointers work. (I haven't touched C in a long while)
int j = 0;
ptr = sizeof(array[j]); //i was thinking this would allocate space
for(j; j < setSize; j++)
array[j].next = array[j+1].next;
ptr = array; //i thought this would point to the beginning of the array
I have looked at a lot of sites about C and linked list. I had books but they don't give enough detail about this particular use of pointers or structures. I have been trying this for a while but I am sure I am missing something.
I just need to understand where I am going wrong and what direction to head towards.
Thanks for any and all help.
Below is a Re-post with more code:
//this should initialize array so that ptr contains all array elements
void initialize ( list array[] ) {
int j;
for(j = 0; j < setSize - 1; j++){
array[j].next = array[j+1].next; //using the & does not seem to work, so I don't use it
array[j].next = NULL;
}
ptr = &(array[0]);
}
Later on I am using this in my own malloc function (which is where the seg fault happens)
//this should allocate a new list cell in array
list* my_malloc () {
list* temp;
temp = ptr;
if(ptr = 0) {printf("Empty!\n"); return;}
else{ //the next line creates the seg fault
ptr = (*ptr).next;
}
return temp;
}
list* cell ( char n, list* next ) {
list* x = my_malloc();
x->value = n;
return x;
x->next = next;
return x;
}
main ( void* argv, int argc ) {
initialize(array);
list* x = nil;
char ch = a;
int i;
for ( i = 0; i < setSize; i++ )
x = cell(ch,x);
for ( i = 0; i < 10; i++ ) {
list* y = x->next;
my_free(x); //this is my own free function
x = y;
};
for ( i = 0; i < 10; i++ )
x = cell(ch,x);
}
Everything you have there is pretty close to making sense except for this line:
ptr = sizeOf(buffer[j]);
I presume you mean sizeof there? At any rate, that operation is meaningless (and illegal, since you're trying to assign an integer to a variable of pointer type). You don't need to allocate any memory, your definition of array already does that.
You do have a problem with your for loop - you're going go one past the end of the array, which might be what's causing your segmentation fault. It's either that or the fact that you didn't initialize j, so it could be accessing some memory it shouldn't. I think you probably want something like:
for (j = 0; j < setSize - 1; j++)
{
array[j].next = &array[j+1];
}
Edit: The reason for your segfault is that this line:
if(ptr = 0) {printf("Empty!\n"); return;}
Sets ptr to 0. I think you want a == there. Another point - you say "using the & does not seem to work, so I don't use it". That probably means your list structure is declared incorrectly, or at least in a pretty nonstandard way. You should probably show more of your program - it seems like you have some pretty fundamental misunderstandings of how pointers work.
I think this is what you want:
#define ARRAY_LENGTH (20)
struct list
{
char ch;
struct list* next;
};
struct list array[ARRAY_LENGTH]; // array's memory is allocated with this, no need to use malloc
struct list* ptr = &(array[0]); // ptr now points to the 1st item in the array
int j; // I'm declaring 'j' outside of the for loop just in case you are using c and not c++
for(j=0 ; j < ARRAY_LENGTH-1 ; j++)
array[j].next = &(array[j+1]); // .next of jth item in array now points to the following item
array[j].next = NULL; // assign .next of last item to NULL, so you know when you have reached the end of the array when traversing it.
Note that the for-loop is executed for (ARRAY_LENGTH - 1) items, not ARRAY_LENGTH items, since array[j+1] would be out of bounds in the last iteration.
Now that you have ptr pointing to the 1st item in the array, you can traverse through it with something like:
struct list* curItem; // this will be your iterator to traverse the array
curItem = ptr; // initialize your iterator to point to the 1st item
while(curItem != NULL) // note that with this, you don't need to know the length of the array
{
printf("Current item's .ch is %c\r\n", curItem->ch); // don't forget to include the header for printf
curItem = curItem->next;
}
array[j].next = array[j+1].next;
That won't work since array[j+1].next isn't defined. Depending on how buffer[i].next is defined, you should be able to do this:
array[j].next = &array[j+1];
sizeof doesn't allocate space. If you don't want to use malloc, you have to allocate your space either on the stack or wherever globals are stored (probably bss). Since you presumably do that with your array definition, ptr = &buffer[j] will get you a pointer to the jth element of the buffer. I think you meant "addressof" instead of "sizeof", which is spelled & in C. Of course, buffer isn't array. That's either a typo or something very wrong.
Anyway, your code is a bit misordered. What you probably wanted to do was initialize your pointer to array, then iterate through the elements, setting next:
ptr = array;
for (j = 0; j < setSize; j++)
array[j].next = &array[j+1];
array[setSize - 1] = NULL; // The last element was set to a lie.