How to copy array of struct in C - c

I have defined struct like
typedef struct {
char *oidkey;
int showperf;
char oidrealvalue[BUFSIZE];
char *oidlimits;
} struct_oidpairs;
and I have array of struct
struct_oidpairs b[] ={{.....},....}
and I want to copy it to new struct array a[]
please help

Something like this:
memcpy(dest, src, sizeof(struct) * sizeof(src));

Your struct contains pointers as data members, this means you will have to roll out your own copy function that will do something sensible with the pointers. memcpy only works is all the data related to the struct is stored in the struct.

For real copy of the contents, follow Sjoerd's answer and then:
for (i = 0; i < sizeof(src); i++)
{
if (src[i].oidkey != NULL)
{
dest[i].oidkey = malloc(strlen(src[i].oidkey) + 1);
strcpy(dest[i].oidkey, src[i].oidkey);
}
if (src[i].oidlimits != NULL)
{
dest[i].oidlimits = malloc(strlen(src[i].oidlimits) + 1);
strcpy(dest[i].oidlimits, src[i].oidlimits);
}
}
You may consider memcpy if you are interested in speed.
Update:
Following harper's code, I
updated the code to check NULL
pointers
This is a quoted note from
gordongekko:
This solution will crash if
oidkey or oidlimits are != NULL and not
'\0'-terminated means not initialized

Makes NOT a deep copy:
struct_oidpairs b[] = {...};
size_t len = sizeof b/sizeof*b;
struct_oidpairs *a = malloc(sizeof b);
if( !a ) /* ERROR handling */
memcpy( a, b, sizeof b );
...
free( a );
or
while( len-- )
a[len] = b[len];
...
free( a );

maybe using :
for(int i=0; i<b.size() ;i++)
//I am not sure if this is the correct name for the size function
{
a[i]=b[i];
}

Related

c - Access violation reading location exception when use scanf to read string from user

I'm trying to get to read string input from user and store it in two dim array using pointers.
I'm getting Access violation reading location exception when trying to use those strings.
first I declared char*** that will store pointers for two dim array , then I use for loop to initial two dim array for each cell.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORDLEN 80
#define DEFLEN 200
#define KEYVALUE 2
char*** MallocDic(int dictionarySize);
char** MallocDicElement(char* word, char* definition);
void PrintDictionary(char*** dictionary, int dictionarySize);
int main()
{
int dictionarySize;
printf("Please enter dictionary size\n");
scanf("%d", &dictionarySize);
char*** dictionary = MallocDic(dictionarySize);
int i;
for (i = 0; i < dictionarySize; i++) {
char* inputWord = (char*)malloc(WORDLEN * sizeof(char));
char* inputDef = (char*)malloc(DEFLEN * sizeof(char));
if (inputWord == NULL || inputDef == NULL)
{
printf("Failed to allocate memory!\n");
exit(1);
}
printf("enter word : \n");
scanf("%s", inputWord);
printf("enter definition : \n");
scanf("%s", inputDef);
printf("word : %s ,def : %s\n", inputWord, inputDef);
//dictionary[i] = MallocDicElement(inputWord, inputDef);
//free(inputDef);
free(inputWord);
}
printf("Print Dictionary : \n");
//PrintDictionary(dictionary, dictionarySize);
}
char*** MallocDic(int dictionarySize) {
char*** p;
p = (char***)malloc(dictionarySize * sizeof(char**));
return p;
}
char** MallocDicElement(char* word, char* definition) {
char** p = (char**)malloc(KEYVALUE * sizeof(char*));
int i;
for (i = 0; i < KEYVALUE; i++) {
if (i == 0) {
p[i] = (char*)malloc(WORDLEN * sizeof(char));
p[i] = word;
}
else {
p[i] = (char*)malloc(DEFLEN * sizeof(char));
p[i] = definition;
}
}
return p;
}
void PrintDictionary(char*** dictionary, int dictionarySize) {
int i = 0, j = 0;
for (i = 0; i < dictionarySize; i++) {
for (j = 0; j < KEYVALUE; j++) {
printf("word : %s\n", dictionary[i][0]);
printf("definition : %s\n", dictionary[i][1]);
}
}
}
The logic breaks in when trying to print the first string.
what am I missing here ?
Thanks for any help.
At least these problems.
Leaked memory
Code allocates memory and saves the pointer to that allocation to p[i] and then copies the pointer word to p[i] in the next line. This loses the pointer returned from malloc().
p[i] = (char*)malloc(WORDLEN * sizeof(char));
p[i] = word; // ???
Much more likely OP wants to copy the string, pointed to by word to the memory pointed to by p[i].
p[i] = malloc(WORDLEN);
strcpy(p[i], word);
More common to allocate only what is needed.
p[i] = malloc(strlen(word) + 1);
strcpy(p[i], word);
Research strdup().
Error checking omitted for brevity.
Do not use "%s", "%[]" without a width in *scanf()
Limit acceptable input to 1 less than the size of the destination array.
"%s" does not read and save spaces
The below will not work to read a definition that contains spaces.
printf("enter definition : \n");
scanf("%s", inputDef); // Stops after first word
Scanning will stop at the first white-space after reading some non-white-space.
Perhaps:
scanf(" %199[^\n]", inputDef);
Check return value of input functions
if (scanf(" %199[^\n]", inputDef) != 1) {
Handle_input_error();
}
Other:
Avoid hard to read & maintain allocation
Rather than cast (not needed) and size to the type (defined someplace else), allocate to the size of the referenced object - no type needed to get wrong.
// p = (char***)malloc(dictionarySize * sizeof(char**));
p = malloc(sizeof p[0] * dictionarySize);
Easier to code right, review and maintain.
At the risk of a non-answer here (not working with your extant code) I would like to suggest you take the time to better structure your data. Even something as simple as:
// A `dictionary` is an array of `capacity` entries, `size` of which are in use.
// Elements are kept in lexicographical order.
struct dictionary
{
struct entry
{
const char * word;
const char * definition;
};
struct entry * entries;
size_t size;
size_t capacity;
};
typedef struct dictionary dictionary;
This makes life about a bazillion times easier when dealing with stuff. You can now create a couple of useful functions:
dictionary * new_dictionary( size_t capacity );
void free_dictionary( dictionary * dict );
This structured nature makes it easier to manage individual parts. In particular, your users can pass the pointer to the dictionary around and never have to worry about it changing. For example, suppose you want to update the dictionary’s capacity:
void set_dicitionary_capacity( dictionary * dict, size_t new_capacity )
{
if (new_capacity < dict->size) return;
struct entry * new_entries = realloc( dict->entries, new_capacity * sizeof dict->entries[0] );
if (!new_entries) return;
dict->capacity = new_capacity;
dict->entries = new_entries;
}
This idea of having functions to interface with your opaque dictionary object is the basis for basic data encapsulation. Doing so makes the using code so much easier:
dictionary * words = new_dictionary( 1000 );
if (!words) fooey();
update_dictionary( words, "hello", "a greeting" );
update_dictionary( words, "world", "the Earth; a planet; any organism’s collective society" );
printf( "There are %zu words in the dictionary.\n", dictionary_size( words ) );
const char * desc = find_word( words, "there" );
printf( "Obi Wan can%s use this dictionary.\n", desc ? "" : "not" );
free_dictionary( words );
Hopefully we can already see how things are easier to grok on every level.
In other words, write code in such a way as to make meaning and structure as clear as possible. This helps to reduce the amount of failure our befuddled minds can generate when writing code.

Dynamically increasing C string's size

I'm currently creating a program that captures user's keypresses and stores them in a string. I wanted the string that stores the keypresses to be dynamic, but i came across a problem.
My current code looks something like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct Foo {
const char* str;
int size;
} Foo;
int main(void)
{
int i;
Foo foo;
foo.str = NULL;
foo.size = 0;
for (;;) {
for (i = 8; i <= 190; i++) {
if (GetAsyncKeyState(i) == -32767) { // if key is pressed
foo.str = (char*)realloc(foo.str, (foo.size + 1) * sizeof(char)); // Access violation reading location xxx
sprintf(foo.str, "%s%c", foo.str, (char)i);
foo.size++;
}
}
}
return 0;
}
Any help would be appreciated, as I don't have any ideas anymore. :(
Should I maybe also allocate the Foo object dynamically?
First, in order to handle things nicely, you need to define
typedef struct Foo {
char* str;
int size
} Foo;
Otherwise, Foo is really annoying to mutate properly - you invoke undefined behaviour by modifying foo->str after the realloc call in any way.
The seg fault is actually caused by sprintf(foo.str, "%s%c", foo.str, (char)i);, not the call to realloc. foo.str is, in general, not null-terminated.
In fact, you're duplicating work by calling sprintf at all. realloc already copies all the characters previously in f.str, so all you have to do is add a single character via
f.str[size] = (char) i;
Edit to respond to comment:
If we wanted to append to strings (or rather, two Foos) together, we could do that as follows:
void appendFoos(Foo* const first, const Foo* const second) {
first->str = realloc(first->str, (first->size + second->size) * (sizeof(char)));
memcpy(first->str + first->size, second->str, second->size);
first->size += second->size;
}
The appendFoos function modifies first by appending second onto it.
Throughout this code, we leave Foos as non-null terminated. However, to convert to a string, you must add a final null character after reading all other characters.
const char *str - you declare the pointer to const char. You cant write to the referenced object as it invokes UB
You use sprintf just to add the char. It makes no sense.
You do not need a pointer in the structure.
You need to set compiler options to compile **as C language" not C++
I would do it a bit different way:
typedef struct Foo {
size_t size;
char str[1];
} Foo;
Foo *addCharToFoo(Foo *f, char ch);
{
if(f)
{
f = realloc(f, sizeof(*f) + f -> size);
}
else
{
f = realloc(f, sizeof(*f) + 1);
if(f) f-> size = 0
}
if(f) //check if realloc did not fail
{
f -> str[f -> size++] = ch;
f -> str[f -> size] = 0;
}
return f;
}
and in the main
int main(void)
{
int i;
Foo *foo = NULL, *tmp;
for (;;)
{
for (i = 8; i <= 190; i++)
{
if (GetAsyncKeyState(i) == -32767) { // if key is pressed
if((tmp = addCharToFoo(f, i))
{
foo = tmp;
}
else
/* do something - realloc failed*/
}
}
}
return 0;
}
sprintf(foo.str, "%s%c", foo.str, (char)i); is ill-formed: the first argument cannot be const char *. You should see a compiler error message.
After fixing this (make str be char *), then the behaviour is undefined because the source memory read by the %s overlaps with the destination.
Instead you would need to use some other method to append the character that doesn't involve overlapping read and writes (e.g. use the [ ] operator to write the character and don't forget about null termination).

Getting a seg fault when trying to append a point in 3D space to the end of an array

I have a function which appends a point in 3D space to the end of an array and then it calculates the time that it takes to append each point. But when I ran my code, it created an initialized the code fine. But when it tried to run the function append, it just seg faulted right away. I've been looking at my code but I can't figure out why it seg faulted. Can anybody help me out?
This is my append code:
int point_array_append( point_array_t* pa, point_t* p)
{
assert( pa );
assert( p );
if( pa->len < pa->reserved )
{
size_t new_res = pa->len * 2 + 1; // add 1 to take care of a NULL array
size_t sz= new_res * sizeof(point_t);
point_t* tmp = realloc( pa->points, sz );
if( tmp == 0 )
return 1; //fail
pa->points = tmp;
pa->reserved = new_res;
}
pa->points[pa->len] = *p; // copy struct into array
pa->len++;
return 0;
}
These are the two structs I use:
typedef struct point
{
double x, y, z; // location in 3D space
} point_t;
typedef struct
{
size_t len; // number of points in the array
point_t* points; // an array of len point_t structs
size_t reserved;
} point_array_t;
Probably you might have a bug in the if condition:
if( pa->len < pa->reserved )
What you probably want is:
if ( <there are no more free slots in the array> )
reallocate
which translates to:
if (pa->len >= pa->reserved)
... do the reallocation

How to convert from string array to int array and then sort it using c

I have string array initialized like that:
char ** strArray;
if ( (strArray = malloc(sizeof(*strArray) + 3)) == NULL ) {
fprintf(stderr, "ls1: couldn't allocate memory");
//exit(EXIT_FAILURE);
}
strArray[0] = NULL;
strArray[0] = "111";
strArray[1] = "222";
strArray[2] = "1";
strArray[3] = "2";
I want to convert this string array to int array, like that:
int * toIntArray(char ** strArray) {
int size = getCharArraySize(strArray);
int intArray[size];
int i;
for ( i = 0; i < size ; ++i)
{
intArray[i] = atoi(strArray[i]);
printf( "r[%d] = %d\n", i, intArray[i]);
}
intArray[size] = '\0';
return intArray;
}
int getCharArraySize(char ** strArray) {
int s = 0;
while ( strArray[s]) {
printf("Char array: %s.\n", strArray[s]);
s++;
}
return s;
}
And then I want to sort this int array.
I must have string array initilized like above (char ** strArray) and then convert this to int array and then sort it. Can anybody help my with that? I would ask about printed sorted integer in main function.
A few minor things to take note of in the question code:
char ** strArray;
if ( (strArray = malloc(sizeof(*strArray) + 3)) == NULL ) {
fprintf(stderr, "ls1: couldn't allocate memory");
//exit(EXIT_FAILURE);
}
If successful, the intention of the above code allocates memory to strArray sufficient for three char *'s. Specifically, strArray[0], strArray1 and strArray[2].
NOTE: As pointed out in Matt McNabb's comment below, it actually incorrectly allocates memory sufficient for one char *, and three extra bytes.
strArray[0] = NULL;
The above line sets sets the first pointer in the **strArray to point at NULL.
strArray[0] = "111";
The above code is odd. After just setting strArray[0] to point at NULL, the above line changes it to point to "111". Kind of makes setting it to NULL (in the first place) seem unnecessary.
strArray[1] = "222";
strArray[2] = "1";
The above two lines initialize the other two pointers in the strArray correctly.
strArray[3] = "2";
The above line attempts to initialize strArray[3], when that element of the array really doesn't exist. So, it is changing something to point to "2", but probably not with the expected result.
Perhaps the intent would be better served by changing the above code to:
char **strArray;
size_t strArrayElements=4;
if(NULL == (strArray = malloc((strArrayElements+1) * sizeof(*strArray))))
{
fprintf(stderr, "ls1: couldn't allocate memory");
exit(EXIT_FAILURE);
}
strArray[strArrayElements] = NULL;
strArray[0] = "111";
strArray[1] = "222";
strArray[2] = "1";
strArray[3] = "2";
As can be observed, the above code allocates 5 elements (strArrayElements+1) to the **strArray. The last element strArray[4] is initialized to NULL; a marker to indicate End-Of-List. Then the other 4 elements [0..3] are initialized.
Now shifting focus to:
int * toIntArray(char ** strArray) {
int size = getCharArraySize(strArray);
int intArray[size];
int i;
for ( i = 0; i < size ; ++i)
{
intArray[i] = atoi(strArray[i]);
printf( "r[%d] = %d\n", i, intArray[i]);
}
intArray[size] = '\0';
return intArray;
}
The above code is successful at converting the strings to their integer forms, and storing them in intArray. However, the code is flawed when it attempts to return intArray to the caller. The intArray variable was declared as a local stack object. The return statement causes all such stack variables to become invalid; and allows the stack memory such variables were using to be used for other things.
Perhaps the the following code better represents what was intended. It allocates memory from the heap for intArray. This allocated memory can outlive the return statement:
int *toIntArray(char **strArray)
{
int size = getCharArraySize(strArray);
int *intArray = malloc(size * sizeof(*intArray));
int i;
for ( i = 0; i < size ; ++i)
{
intArray[i] = atoi(strArray[i]);
printf( "r[%d] = %d\n", i, intArray[i]);
}
intArray[size] = '\0';
return(intArray);
}
Spoiler code may be found here.

HOW TO: Deep Copy of Linked List

I am having some issues with a program I am writing in C, and I have surpassed my knowledge. In summary, I need to deep copy a link list from one list to another. The lists have malloc'd data in them and I need to preserve all the data without having pointers pointing at the same information.
I have only posted the code that I think is relevant. If I am missing any important contextual information please let me know.
Here is the code:
matrix.h
typedef struct matrix {
char *name;
int R;
int C;
int dim;
void (*concat_matrices)( struct matrix *A, struct matrix *B, struct matrix *ret );
} Matrix;
void concat_matrices( Matrix *A, Matrix *B, Matrix *ret ) {
int L1 = strlen( A->name );
int L2 = strlen( B->name );
int len = L1 + L2;
char *Ap = (char*)malloc(L1*sizeof(char)); strcpy(Ap,A->name);
char *Bp = (char*)malloc(L2*sizeof(char )); strcpy(Bp,B->name);
char *c = (char*)malloc(sizeof(char)*(len + 2));
c[0] = '('; strcat(c, Ap); strcat(c, Bp); c[len+1] = ')';
ret->name = (char*)malloc(sizeof(char)*(len + 2));
strcpy(ret->name, c);
ret->R = A->R; ret->C = B->C;
ret->dim = ret->R*ret->C;
free(Ap); free(Bp); free(c);
}
matrix_list.h
typedef struct node {
Matrix *M;
struct node *next;
struct node *prev;
} Node;
typedef struct matrix_list {
Node *head;
Node *tail;
int size;
void (*append)( struct matrix_list *list, Matrix *M );
void (*print)( struct matrix_list *list );
void (*reverse_print)( struct matrix_list *list );
void (*delete)( struct matrix_list *list, const char *name );
void (*delete_tail)( struct matrix_list *list );
void (*delete_head)( struct matrix_list *list );
void (*release)( struct matrix_list *list );
void (*clone_list)( struct matrix_list *from, struct matrix_list *to );
} MatrixList;
...
void clone_list( MatrixList *from, MatrixList *to ) {
if( from->head == NULL ) {
to = NULL;
} else {
Node *tmp = from->head;
while( tmp != NULL ) {
Matrix *m_copy = (Matrix*)malloc(sizeof(Matrix*));
char *c_copy = (char*)malloc(sizeof(char*)*strlen(tmp->M->name));
strcpy(c_copy,tmp->M->name);
m_copy->name=c_copy;
m_copy->R=tmp->M->R;
m_copy->C=tmp->M->C;
m_copy->concat_matrices = concat_matrices;
to->append( to,m_copy );
tmp = tmp->next;
}
}
}
main.c
chain->print(chain);
MatrixList *chain_copy = (MatrixList*)malloc(sizeof(MatrixList));
set_list_functions( chain_copy );
chain->clone_list(chain, chain_copy);
chain_copy->print(chain_copy);
The problem arises when I try and print out the clone. Because I am malloc'ing in the clone function I understand the data goes out of scope. How can I do this copy so after the function is called clone has its own version of the data?
UPDATE:
First I would like to thank you all for taking your time to answer my question, and for teaching me more about C. I have only been coding for about 3 years. And I have a lot to learn. The updated source with 0 errors from Valgrind can be found at.
http://matthewh.me/Scripts/c++/matrix_chain/ for anyone else trying to figure out things like me. User = guest Password = guest. The clone_list function now looks like this.
void clone_list( MatrixList *from, MatrixList *to ) {
if( from->head == NULL ) {
to = NULL;
} else {
Node *tmp = from->head;
while( tmp != NULL ) {
Matrix *m_copy = (Matrix*)malloc(sizeof(Matrix));
m_copy->name = (char*)malloc(strlen(tmp->M->name) + 1);
sprintf( m_copy->name, "%s", tmp->M->name );
m_copy->R=tmp->M->R;
m_copy->C=tmp->M->C;
m_copy->concat_matrices = concat_matrices;
to->append( to,m_copy );
tmp = tmp->next;
}
}
}
If anyone else sees anything else wrong and would like to add additional pointers please feel free to do so.
You haven't allowed for the null that terminates strings, so you have classic buffer overflows.
You also do not need to copy the names three times. Your current code is:
int L1 = strlen( A->name );
int L2 = strlen( B->name );
int len = L1 + L2;
char *Ap = (char*)malloc(L1*sizeof(char)); strcpy(Ap,A->name);
char *Bp = (char*)malloc(L2*sizeof(char )); strcpy(Bp,B->name);
char *c = (char*)malloc(sizeof(char)*(len + 2));
c[0] = '('; strcat(c, Ap); strcat(c, Bp); c[len+1] = ')';
ret->name = (char*)malloc(sizeof(char)*(len + 2));
strcpy(ret->name, c);
ret->R = A->R; ret->C = B->C;
ret->dim = ret->R*ret->C;
free(Ap); free(Bp); free(c);
This should be:
int L1 = strlen(A->name);
int L2 = strlen(B->name);
ret->name = (char *)malloc(L1 + L2 + sizeof("()")); // That adds 3
sprintf(ret->name, "(%s%s)", A->name, B->name);
ret->R = A->R;
ret->C = B->C;
ret->dim = ret->R * ret->C;
This eliminates Ap, Bp and c altogether, and avoids the buffer overflow problems. I'm not sure I'd slam the two names together like you do, but that's your choice.
Apparently, this isn't sufficient of a problem...there are other issues too.
void clone_list( MatrixList *from, MatrixList *to ) {
if (from->head == NULL) {
to = NULL;
} else {
Node *tmp = from->head;
while( tmp != NULL ) {
Matrix *m_copy = (Matrix*)malloc(sizeof(Matrix*));
char *c_copy = (char*)malloc(sizeof(char*)*strlen(tmp->M->name));
strcpy(c_copy,tmp->M->name);
m_copy->name=c_copy;
m_copy->R=tmp->M->R;
m_copy->C=tmp->M->C;
m_copy->concat_matrices = concat_matrices;
to->append( to,m_copy );
tmp = tmp->next;
}
}
}
The first assignment zeroes the local pointer; it doesn't do a thing to the MatrixList passed in as the target. This should presumably be:
if (from->head == 0)
{
*to = *from;
}
This does a wholesale structure copy, but sets the head and tail to null, and the function pointers are all fine - they can be shared. Assuming that the size in from was correctly zero, it will be correct in to too. (Again, this is probably not the code you are exercising.)
The next problem is with the memory allocation:
Matrix *m_copy = (Matrix*)malloc(sizeof(Matrix*));
This allocates one pointer's worth of memory, not one Matrix's worth. Use either of these:
Matrix *m_copy = (Matrix *)malloc(sizeof(*m_copy));
Matrix *m_copy = (Matrix *)malloc(sizeof(Matrix));
That is a major source of your trouble (and one which valgrind will find easily).
When the +1 gets forgotten once, it gets forgotten many times, but this time it doesn't cause problems unless the name is the empty string because you multiply by 4 or 8 (32-bit or 64-bit) because of the sizeof(char *) instead of the intended sizeof(char).
char *c_copy = (char*)malloc(sizeof(char*)*strlen(tmp->M->name));
strcpy(c_copy,tmp->M->name);
This should probably be:
m_copy->name = (char *)malloc(strlen(tmp->M->name) + 1);
strcpy(m_copy->name, tmp->M->name);
I'd probably use a name like old instead of tmp. I am also remiss in not reminding previously that you should religiously check every return from every memory allocation. Or use a set of cover functions for the memory allocation routines which do the check for you (often called xmalloc() or emalloc(), etc.).
The code below that does not seem to copy the dim member across, which is a bug if you ever depend on it.
I'm not entirely happy that you seem to rely on the to list being appropriately initializes before calling clone_list(). In particular, the head, tail and size members are not zeroed here, and the function pointers are not set. I'd be happier to see something like:
*to = *from; // Copy function pointers
to->head = 0;
to->tail = 0;
to->size = 0;
Node *old = from->head;
for (Node *old = from->head; old != NULL; old = old->next)
{
Matrix *m_copy = clone_matrix(old->M);
to->append(to, m_copy);
}
Or even:
matrixlist_initialize(to);
Node *old = from->head;
for (Node *old = from->head; old != NULL; old = old->next)
{
Matrix *m_copy = clone_matrix(old->M);
to->append(to, m_copy);
}
The clone_matrix() function looks like:
Matrix *clone_matrix(const Matrix *old)
{
Matrix *m_copy = (Matrix*)malloc(sizeof(*m_copy));
m_copy->name = (char*)malloc(strlen(old->name)+1);
strcpy(m_copy->name, old->name);
m_copy->R = old->R;
m_copy->C = old->C;
m_copy->dim = old->dim;
m_copy->concat_matrices = concat_matrices;
return(m_copy);
}
I downloaded a version your code and it now seems to work, more or less. You should be compiling with at least -Wall as a compiler option; I refuse to compile with anything less and usually use -Wextra too. I make too many simple-to-spot mistakes not to make full use of the compiler, and while you are learning, you will too. (I've only been coding in C for just over a quarter century; the compiler still catches typos and other silly mistakes, but I seldom have big problems once the code is compiling.)
When I turned on -Wall, there was a problem with the (unused) perm() function because it doesn't return a value even though it says it will, and there was a problem because the correct definition for main() with arguments is int main(int argc, char **argv) and you were missing one of the stars. Other than that, it seems to be working OK now - you can continue with your development.
There is a function in POSIX called strdup() which duplicates a string reliably. It is useful and avoids the off-by-one mistakes.
You should review the use of headers. They are for declarations, primarily. If you explicitly use inline (your code doesn't yet), it can be appropriate to include inline functions in a header, but otherwise, function bodies should not be in headers. They should be in source files (.c suffix). Each header should contain the minimum necessary information for the code that uses the functionality provided by the source to use. It should not include extraneous headers, but it should include all necessary headers. In matrix.h, you include <stdio.h> which is unnecessary. And if you removed the code, neither <string.h> nor <stdlib.h> would be needed either.
int L1 = strlen( A->name );
int L2 = strlen( B->name );
int len = L1 + L2;
char *Ap = (char*)malloc(L1*sizeof(char)); strcpy(Ap,A->name);
char *Bp = (char*)malloc(L2*sizeof(char )); strcpy(Bp,B->name);
I'm willing to bet that your strcpy(3) calls here have written outside the bounds of the memory you've allocated: strlen(3) does NOT account for the '\0' terminator at the end of C strings, so your *Ap and *Bp are allocated one-byte-too-short.
Because this is so common it is an easy pattern to find bugs:
int len = strlen(s);
char *new = malloc(len); /* FAIL */
If I don't see a + 1 in the malloc(3) call, it's almost certainly a bug. :) I prefer to see:
int len = strlen(s);
char *new = malloc(len + 1);
rather than:
int len = strlen(s) + 1;
char *new = malloc(len);
If you follow the former, I think it is far easier to spot the wrong cases when you forget the + 1. I think the latter one is too easy to overlook the wrong ones amidst a sea of correct ones.
Similarly, your c and ret->name have been allocated too short.
But, I think there is a far easier answer:
void concat_matrices( Matrix *A, Matrix *B, Matrix *ret ) {
int len = strlen(A->name) + strlen(B->name) + 2 + 1; /* parens + NUL */
ret->name = malloc(len);
sprintf(ret->name, "(%s%s)", A->name, B->name);
ret->R = A->R; ret->C = B->C;
ret->dim = ret->R*ret->C;
}
Use sprintf(3) to build the string in one fell swoop. You only need to allocate one string, and that's the one you intend to keep, which will reduce memory fragmentation due to frequent allocate / deallocate cycles. But the most important reason for the re-write is I think this new version is easier to read. Note I broke my rule about the + 1 here -- clarity is improved by adding together all the memory required in one line.
Update
Your clone_list() function suffers from the same problem:
Matrix *m_copy = (Matrix*)malloc(sizeof(Matrix*));
char *c_copy = (char*)malloc(sizeof(char*)*strlen(tmp->M->name));
strcpy(c_copy,tmp->M->name);
Your m_copy looks fine, because it is a binary object and the size is known exactly. But c_copy is allocated one byte too short -- it is not long enough to contain the '\0' byte that is copied into place with the strcpy(3) call immediately following. This routine too is scribbling over unallocated memory.

Resources