Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Let's say a function allocates memory for a string and returns it.
The variable, that calls that function, in which is stored its return string is an array of pointers to char already dynamically allocated.
My doubt is, when I'll free the variable's memory, is it going to free both the variable memory and the in-function string memory or does the in-function allocated memory became one with the variable one?
char *function() {
//allocates memory for <string>
return <string>
}
int main() {
//<variable> declaration
//<variable> allocation
<variable> = function();
free(<variable>);
return 0;
}
For practical reasons I omitted the //function declaration part
Thanks for your attention and help!
There are two possible cases:
Function allocates memory using dynamic memory allocation and it is 100% correct
char *func(void)
{
char *x = malloc(100);
/* some code */
return x;
}
void foo(void)
{
char *y = func();
free(y);
}
Other ways of allocating memory. All invoke the undefined behavior when you try to free them. Additionally there is an another UB when pointer to automatic variable is used outside the scope it was defined in.
char w[100];
char *func(void)
{
char x[100];
/* some code */
return x;
}
char *func1(void)
{
static char x[100];
/* some code */
return x;
}
char *func2(void)
{
return w;
}
void foo(void)
{
char *y = func();
y[0] = 'a'; //UB
free(y); //UB
y = func1();
y[0] = 'a';
free(y); //UB
y = func2();
y[0] = 'a';
free(y); //UB
}
I posted a complete example of it here: https://stackoverflow.com/a/63756135/11234199
My doubt is, when I'll free the variable's memory, is it going to free both the variable memory and the in-function string memory or does the in-function allocated memory became one with the variable one?
Please run the program provided there since it will do just this: create and destroy a block of pointers to char, just like argc/argv block that every main() function gets for free in C
The program I posted there shows how to build dynamically a block of strings and how to consume it, allocating memory in blocks and trimming it at the end for the exact used size
But here I will provide a 20-line example that builds an array of pointer the same way
Your function
char *function()
{
//allocates memory for <string>
return <string>
}
returns just one pointer to a char. You could write
char one_char = *function();
and it is just what is is. There is not string in C in fact. And if function is char* then *function is char.
Inside the function you can malloc() a block and return the address in the function, with a convenient '\0' at the start of a 1MB block and it would be fine.
For this thing to work we need to build it carefully
Fact is that in general we want something like
typedef struct
{
int argc;
char** argv;
} stringArray;
just like the familiar main() prototype.
And why is that?
Well, we want an array of pointers to char due to the conveniente of iterate through hem just like an ordinary array like argv[0], argv[1]...
But it is essential the argc thing. As in
char** argv;
we have no way to know how many pointers are in the area pointed by *argv.
we just know that
argv is char**
*argv is char*, a pointer to char
**argv is a char, a single char
we have to build the block the way we need, or just hope that someone gently did that before we use.
If there are one hundred strings at *argv it is because someone allocated 100 pointers to char and put the address in argv. And after that allocated 100 strings of who knows what size, using the one hundred pointers. And then made sure the strings are all null-terminated.
This is how it works.
The code below builds an example 10-string block, and just for fun the strings are build the way we see here:
we got 10 strings:
'0' [len: 1]
'01' [len: 2]
'012' [len: 3]
'0123' [len: 4]
'01234' [len: 5]
'012345' [len: 6]
'0123456' [len: 7]
'01234567' [len: 8]
'012345678' [len: 9]
'0123456789' [len: 10]
End of list
And back in main() the the full block is destroyed from inside out.
here is the code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int argc;
char** argv;
} stringArray;
stringArray* get_the_block(void);
int main(void)
{
stringArray* string_array = get_the_block();
printf("we got %d strings:\n\n", string_array->argc);
char** array = string_array->argv; // just for readability
for (int i = 0; i < string_array->argc; i += 1)
printf("'%s' [len: %zd]\n", array[i], strlen(array[i]));
printf("\nEnd of list\n");
// free() the block
// since string_array is also a pointer we have 3 levels
// 1st free() the strings
for (int i = 0; i < string_array->argc; i += 1)
free(array[i]);
// 2nd free() the block of pointers
free(string_array->argv);
// 3rd free() the control structure
free(string_array);
return 0;
}; // main()
stringArray* get_the_block(void)
{
// this is an useless example
// it builds a 10-string block and
// return it
const char* text = { "0123456789" };
// building the block of strings
// "0", "01", "012" ... "123456789"
char** string = (char**)malloc(10 * sizeof(char*));
for (int i = 0; i < 10; i += 1)
{
string[i] = malloc((1 + 1 + i) * sizeof(char));
memcpy(string[i], text, 1 + i);
string[i][i + 1] = 0; // strings are null-terminated
};
// builds the struct to return, just like the system
// does for main()
stringArray* block = (stringArray*)malloc(sizeof(stringArray));
block->argc = 10;
block->argv = string;
return block;
};
The variable, that calls that function, in which is stored its return
string is an array of pointers to char already dynamically allocated.
It means that the returned pointer from the function can be assigned only to one element of the dynamically allocated array.
For example
char **s = malloc( 10 * sizeof( char * ) );
s[0] = function();
So you may free the memory allocated in the function and the pointer to which was assigned to the element s[0] like
free( s[0] );
After that you may for example reassign the pointer with an address of other dynamically allocated string.
But this call will not free the memory allocated for the whole array of pointers s. To free it you have to write
free( s );
Related
I am doing a bit of studying about C pointers and how to transfer them to functions, so I made this program
#include <stdio.h>
char* my_copy(pnt);
void main()
{
int i;
char a[30];
char* p,*pnt;
printf("Please enter a string\n");
gets(a);
pnt = a;
p = my_copy(pnt);
for (i = 0; i < 2; i++)
printf("%c", p[i]);
}
char* my_copy(char* pnt)
{
char b[3];
char* g;
g = pnt;
b[0] = *pnt;
for (; *pnt != 0; pnt++);
pnt--;
b[1] = *pnt;
b[2] = NULL;
return b;
}
It's supposed to take a string using only pointers and send a pointer of the string to the function my_copy and return a pointer to a new string which contains the first and the last letter of the new string. Now the problem is that the p value does receive the 2 letters but I can't seem to print them. Does anyone have an idea why?
I see five issues with your code:
char* my_copy(pnt); is wrong. A function prototype specifies the types of the parameters, not their names. It should be char *my_copy(char *).
void main() is wrong. main should return int (and a parameterless function is specified as (void) in C): int main(void).
gets(a); is wrong. Any use of gets is a bug (buffer overflow) and gets itself has been removed from the standard library. Use fgets instead.
b[2] = NULL; is a type error. NULL is a pointer, but b[2] is a char. You want b[2] = '\0'; instead.
my_copy returns the address of a local variable (b). By the time the function returns, the variable is gone and the pointer is invalid. To fix this, you can have the caller specify another pointer (which tells my_copy where to store the result, like strcpy or fgets). You can also make the function return dynamically allocated memory, which the caller then has to free after it is done using it (like fopen / fclose).
You're returning an array from my_copy that you declared within the function. This was allocated on the stack and so is invalid when the function returns.
You need to allocate the new string on the heap:
#include <stdlib.h>
b = malloc(3);
if (b) {
/* Do your funny copy here */
}
Don't forget to free() the returned string when you've finished with it.
What would be the C code for a function that accepts a pointer to a character as argument and returns a pointer to an array of integers?
I have a confusion here. My answer is as follows:
int * q (char *) [ ]
Im not sure if I'm correct. But if its incorrect then what is the correct answer more importantly what is the approach to answer it. In general i would appreciate any general method to learn to interpret such questions and convert them to C code?
When dealing with functions, you basically needs to consider arrays as pointers because it is very hard (if possible) to pass or return an array in a function and make operations such as the sizeof operator still work as intended.
For you purpose, int ** q (char *) is enough, although you would not be able to know the length of the returned array this way.
A pointer to an array of integers looks like:
int (*p)[];
where it is optional to have a dimension inside the square brackets.
So a function returning that would look like:
int (*func(char *))[];
Note that "pointer to array" is a different thing to "pointer to first element of array". Sometimes people say the former when they mean the latter. If you actually meant the latter then your function could be more simply:
int **func(char *);
The first form is rarely used because there is nothing you can do with the return value other than decay it to int ** anyway. It would sometimes be useful to specify a dimension if the function always is to return a pointer to a fixed-size buffer, but in that case I would recommend using a typedef for readability:
typedef int ARR_4_INT[4];
ARR_4_INT * func(char *);
I think I see where your confusion is, and I'm not sure it has been cleared based on the answer you selected. int **q (char *) is a function that returns a pointer to pointer to int, which if that is what you need, that is fine, but understand, the only way a function can return a pointer to pointer to int is if (1) the address of an array of int (pointer to array) is passed as a parameter to q, or (2), pointers are allocated in q and the pointer to allocated pointers is returned.
You appear to want (1), but have selected an answer for (2). Take a look at cdecl.org (C-declarations tool) which can always help decipher declarations
The best way to help you sort it out is probably an example of each. The following examples just plays on the ASCII value of the character variable c (ASCII '5' by default -- decimal 53). In the first case, returning a pointer-to-int (which is a pointer to a block of memory holding zero or more integers). For example, here a block of memory is allocated to hold 53 integers filled with values from 53-105:
#include <stdio.h>
#include <stdlib.h>
int *q (char *c)
{
int *a = calloc (*c, sizeof *a);
if (a)
for (int i = 0; i < (int)*c; i++)
a[i] = *c + i;
return a;
}
int main (int argc, char **argv) {
char c = argc > 1 ? *argv[1] : '5';
int *array = NULL;
if ((array = q (&c)))
for (int i = 0; i < (int)c; i++)
printf ("array[%3d] : %d\n", i, array[i]);
free (array); /* don't forget to free mem */
return 0;
}
Now in the second case, you are returning a pointer-to-pointer-to-int (a pointer to a block of memory holding zero or more pointers to int -- which each in turn can be separately allocated to hold zero or more integers each). In this case each individual pointer is allocated with space to hold one int and the same values as above are assigned:
#include <stdio.h>
#include <stdlib.h>
int **q (char *c)
{
int **a = calloc (*c, sizeof *a); /* allocate *c pointers to int */
if (a) {
for (int i = 0; i < (int)*c; i++)
if ((a[i] = calloc (1, sizeof **a))) /* alloc 1 int per-pointer */
*(a[i]) = *c + i;
else {
fprintf (stderr, "error: memory exhausted.\n");
break;
}
}
return a;
}
int main (int argc, char **argv) {
char c = argc > 1 ? *argv[1] : '5';
int **array = NULL;
if ((array = q (&c)))
for (int i = 0; i < (int)c; i++) {
printf ("array[%3d] : %d\n", i, *(array[i]));
free (array[i]); /* free individually allocated blocks */
}
free (array); /* don't forget to free pointers */
return 0;
}
Example Use/Output
In each case, if no argument is passed to the program, the default output would be:
$ ./bin/qfunction2
array[ 0] : 53
array[ 1] : 54
array[ 2] : 55
...
array[ 50] : 103
array[ 51] : 104
array[ 52] : 105
Now it is entirely unclear which of the two cases you are after as you seem to explain you want a pointer to an array of integers returned. As I started my last answer with, you cannot return an array, all you can return is a pointer, but that pointer can point to a block of memory that can hold multiple integers, or it can point to a block of memory holding multiple pointers that can each in turn be allocated to hold multiple integers.
So the ambiguity comes in "Do you want the return to point to an array of integers or an array of pointers?" int *q (char *) is for the first, int **q (char*) is for the second.
Now, going forward, you will realize that you have not provided a way to know how many integers (or pointers) are being returned. (that requires an extra parameter or global variable (discouraged) at the very least). That is left for another day. (it is also why the examples are a play on the ASCII value of 53 or whatever character is the first character of the first argument, it provides a fixed value to know what has been allocated)
I'm happy to provide further help, but I will need a bit of clarification on what you are trying to accomplish.
I used this code to print some string,but it does not print any thing.What is the problem?
char* getNotFilledEncryptionParams(void)
{
char* nofilledStr;
char tmp[3];
const char * arr[]= {" P,"," Q,"," A,"," B,"," C,"," R,"," S0,","S1,","S2,","F1,","G1"};
for(i=0;i<11;i++)
{
if(filledParams[i] == 0)
{
strcpy(tmp,arr[i]);
strcat(nofilledStr,tmp);
}
}
return nofilledStr;
}
Usage:
int main(void){
char *remaining;
remaining = getNotFilledEncryptionParams();
printf("\r\n Remaining item:%s",remaining);
}
I think the problem is in const char * arr[] and I changed it,but the problem remains.
You didn't allocate any memory for noFilledStr, so its value is indeterminate and strcat(noFilledStr, tmp) is undefined.
Use malloc to allocate memory and initialize noFilledStr with the returned pointer:
char* noFilledStr = malloc(number_of_bytes);
The strings in arr are char[4], not char[3] (do not forget the null byte!). tmp is too small to hold them, so strcpy(tmp, arr[i]) writes out of bounds.
You are trying to build the string to return in the location pointed to by nofilledStr but this pointer is pointing somewhere as you do not initialize it. You could use a sufficiently large static char[] array if you do not have to deal with multiple threads. Otherwise, use malloc() and require the caller to free() the returned string when he is done with it.
I'm learning C and trying to figure out an elegant way to free my pointers at the end of the execution.
After hours debugging and experimenting different things with the following code, I couldn't manage to figure out what I was doing wrong:
int ClosePointers(char *pointersToClose[], int arraySize) {
int index;
for(index = 0; index < arraySize; index++) {
char *pointer = pointersToClose[index];
free(pointer);
}
return (0);
}
int main(int argc, char *argv[]) {
char *pointersToClose[4];
char *pointer1;
char *pointer2;
char *pointer3;
char *pointer4;
pointersToClose[0] = pointer1;
pointersToClose[1] = pointer2;
pointersToClose[2] = pointer3;
pointersToClose[3] = pointer4;
pointer1 = malloc(10);
pointer2 = malloc(10);
pointer3 = malloc(10);
pointer4 = malloc(10);
/*some important code here using the pointers*/
ClosePointers(pointersToClose, 4);
return 0;
}
I'm getting the following error:
* glibc detected * /home/workspace/Debug/Test-POC: free(): invalid pointer: 0x00000038ce7b9850 ***
Could you help me out pointing what I'm doing wrong?
You're calling free on those pointers, but you never allocate any memory to them with malloc. In fact, the pointers you are trying to free are uninitialized, so they could contain anything.
When you set the values of pointersToClose, you're assigning the current value of pointer1, pointer2, etc., not whatever value they may contain when "some important code here using the pointers" runs.
Passing a pointer value to free that was not returned by malloc/realloc/calloc results in undefined behavior.
If you want to do this, try putting the address of each of the pointers in question in your array.
int ClosePointers(char **pointersToClose[], int arraySize) {
int index;
for(index = 0; index < arraySize; index++) {
char **pointer = pointersToClose[index];
free(*pointer);
}
return (0);
}
int main(int argc, char *argv[]) {
char **pointersToClose[4];
char *pointer1;
char *pointer2;
char *pointer3;
char *pointer4;
pointersToClose[0] = &pointer1;
pointersToClose[1] = &pointer2;
pointersToClose[2] = &pointer3;
pointersToClose[3] = &pointer4;
/*some important code here using the pointers*/
ClosePointers(pointersToClose, 4);
return 0;
}
Could you help me out pointing what I'm doing wrong?
You should use free() only on pointers that you allocated on the heap using the malloc() function.
What happens, is that within the heap (a reserved memory space), the length you gave as parameter to the malloc() function is allocated for your use, and it returns the address to the first word of that memory space so it can be assigned to a pointer.
When you use free(), it's deallocating that memory space so it can be reused.
Here, you create pointers variables that points to nothing (actually they point to a random value). So what's happening when you call free() on those variables is that you try to deallocate some random memory space that is not within the managed space, called the heap. As those addresses are unlikely to be allocated by malloc(), the free() function cannot know what to do with it, and therefore will return an error!
Read on about what are the stack and the heap to better understand what those are. Also, read the C programming language book by Kernighan and Ritchie where it's all well explained.
In your code. pointer1 is unitialized. It points to invalid memory. Passing that to free() invokes undefined behavior.
Quoting C11, chapter ยง7.22.3.3, (emphasis mine)
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if
the argument does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to free or realloc, the
behavior is undefined.
You need to either
set that to NULL (null-pointer constant)
use malloc() or family to allocate free-able memory first.
That said, pointer2, pointer3 and pointer4 are undeclared in your code but probably that's a typo, so we can overlook it.
In order to free a pointer you must first have allocate memmory for it. You are going to free pointers that are never allocated. Try the following code to understnd what you did wrong
int AllocatePointers(char *pointersToClose[], int arraySize) {
int index;
for(index = 0; index < arraySize; index++) {
pointersToClose[index] = malloc(50*sizeof(char));
}
return (0);
}
int main(int argc, char *argv[]) {
char *pointersToClose[4];
char *pointer1;
char *pointer2;
char *pointer3;
char *pointer4;
pointersToClose[0] = pointer1;
pointersToClose[1] = pointer2;
pointersToClose[2] = pointer3;
pointersToClose[3] = pointer4;
AllocatePointers(pointersToClose, 4);
/*some important code here using the pointers*/
ClosePointers(pointersToClose, 4);
return 0;
}
So I'm working through "Sams Teach Yourself C Programming in One Hour a Day, Seventh Edition" Lesson 10 Exercise 7 which asks to "Write a function that accepts two strings. Use the malloc() function to allocate enough memory to hold the two strings after they have been concatenated (linked). Return a pointer to this new string."
I am sure there are much more elegant ways to go about this than what I have attempted below. I am mostly interested in why my solution doesn't work. I have only been learning C for a few months and have no significant programming background. Please let me know why this crashes on compilation. I am using Code Blocks on Win 7 with GNU GCC Compiler if that makes a difference. Thank you :)
#include <stdio.h>
#include <stdlib.h>
char * concatenated(char array1[], char array2[]);
int ctrtotal;
int main(void)
{
char *comboString;
char *array1 = "You\'re the man ";
char *array2 = "Now Dog!";
comboString = (char *)malloc(ctrtotal * sizeof(char));
concatenated(array1, array2);
if (comboString == NULL)
{
puts("Memory error");
exit(1);
}
puts(comboString);
free(comboString);
return 0;
}
char * concatenated(char array1[], char array2[])
{
char *array3;
int ctr;
int ctr2;
for (ctr = 0; array1[ctr] != '\0'; ctr++)
array3[ctr] = array1[ctr];
ctr2 = ctr;
for (ctr = 0; array2[ctr] != '\0'; ctr++)
{
array3[ctr2 + ctr] = array2[ctr];
}
array3[ctr2 + ctr + 1] = '\0';
ctrtotal = (ctr2 + ctr + 2);
return array3;
}
Thank you for the help. After reviewing everyone's feedback on my errors I revised the code to the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * concatenated(char array1[], char array2[]);
int main(void)
{
char *array1 = "Testing Testing One Two ";
char *array2 = "Three. Finally, not crashing the mem o ry.";
char *comboString = malloc( (strlen(array1)+strlen(array2) + 1)*sizeof(char));
comboString = concatenated(array1, array2);
if (comboString == NULL)
{
puts("Memory error");
exit(1);
}
puts(comboString);
free(comboString);
return 0;
}
char * concatenated(char array1[], char array2[])
{
char *array3;
array3 = malloc( (strlen(array1)+strlen(array2) + 1)*sizeof(char) );
strcat(array3, array1);
strcat(array3, array2);
return array3;
}
If anyone sees any redundancies/unnecessary remaining code the could/should be deleted, please let me know. I recognize the benefit of being as concise as possible.
Your code has a bunch of issues:
int ctrtotal is never initialized, so you are mallocing 0 bytes
concatenated() is copying characters to an uninitialized array3. This pointer should point to a mallocd buffer.
If concatenated is allocating the memory, then main doesn't need to. Instead it should use the result of concatenated.
I don't want to give you the full code, and let you to miss out on this learning opportunity. So concatenated should look like this, in psuedo-code:
count = length_of(string1) + length_of(string2) + 1
buffer = malloc(count)
copy string1 to buffer
copy string2 to buffer, after string1
set the last byte of buffer to '\0' (NUL)
return buffer
In C, strings are represented as a NUL-terminated array of characters. That's why we allocate one additional byte, and terminate it with \0.
As a side-note, when dealing with strings, it is far easier to work with pointers, instead of treating them as arrays and accessing them via indices.
There's a lot of code here that just doesn't make any sense. I suggest that you first write this program on paper. Then, "execute" the program in your head, stepping through every line. If you get to something you don't understand, then you need to either fix your understanding, or your incorrect code. Don't try to write code that looks like some other bit of code.
There's also a library function called strcat which will make this task even easier. See if you can figure out how to use it here.
Spoiler --> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *concatenate2(const char* s1, const char* s2);
int main(void)
{
char *comboString;
char *array1 = "You're the man ";
char *array2 = "Now Dog!";
comboString = concatenate2(array1, array2);
if (comboString == NULL)
{
puts("Memory error");
exit(1);
}
puts(comboString);
free(comboString);
return 0;
}
char *concatenate2(const char* s1, const char* s2)
{
char *result;
result = malloc(strlen(s1) + strlen(s2) + 1);
*result = '\0';
strcat(result, s1);
strcat(result, s2);
return result;
}
You forgot to allocate memory for third, concatenated, array of chars (in function)
You should do something like this:
char *array3;
array3 = (char *)malloc( (strlen(array1)+strlen(array2) + 1)*sizeof(char) ); // +1 for '\0' character.
and then write chars from first and second array into third.
Perhaps a stroll through the question code is best.
#include <stdio.h>
#include <stdlib.h>
char * concatenated(char array1[], char array2[]);
int ctrtotal;
Notice that the above line declares ctrtotal to be an integer, but does not specify the value of the integer.
int main(void)
{
char *comboString;
char *array1 = "You\'re the man ";
char *array2 = "Now Dog!";
comboString = (char *)malloc(ctrtotal * sizeof(char));
Notice that the above line allocates memory and sets 'comboString' to point at that memory. However, how much memory is being allocated?
(ctrtotal[???] * sizeof(char)[1])
What is the value of (??? * 1) ? This is a problem.
concatenated(array1, array2);
The intent of the line above is that array1["You\'re the man "] and array2["Now Dog!"] will be joined to form a new string["You\'re the man Now Dog!"], which will be placed in allocated memory and returned to the caller.
Unfortunately, the returned memory containing the string is not captured here. For example, perhaps the above line should be:
comboString = concatenated(array1, array2);
While this make sense, for this line, it begs a question of the purpose of the lines:
comboString = (char *)malloc(ctrtotal * sizeof(char));
as well as the global variable:
int ctrtotal;
and the later reference:
ctrtotal = (ctr2 + ctr + 2);
Perhaps all of these 3 lines should be deleted?
if (comboString == NULL)
{
puts("Memory error");
exit(1);
}
puts(comboString);
free(comboString);
return 0;
}
char * concatenated(char array1[], char array2[])
{
char *array3;
Notice that '*array3' is now a defined pointer, but it is not pointing anywhere specific.
int ctr;
int ctr2;
The purpose of 'concatenated()' is to join array1 and array1 into allocated array3. Unfortunately, no memory is allocated to array3.
Below, the memory where array3 is pointing will be modified. Since array3 is not pointing anywhere specific, this is not safe.
Prior to modifying memory where array 3 is pointing, it is important to point array3 at memory where it is safe to modify bytes. I suggest that the following code be inserted here:
array3 = malloc(strlen(array1) + strlen(array2) + 1);
Now, array3 points to allocated memory, large enough to hold both strings plus the string termination character '\0'.
for (ctr = 0; array1[ctr] != '\0'; ctr++)
array3[ctr] = array1[ctr];
ctr2 = ctr;
for (ctr = 0; array2[ctr] != '\0'; ctr++)
{
array3[ctr2 + ctr] = array2[ctr];
}
array3[ctr2 + ctr + 1] = '\0';
ctrtotal = (ctr2 + ctr + 2);
return array3;
}
I am responding to your revised code. There are a few bugs in it.
...
char *array2 = "Three. Finally, not crashing the mem o ry.";
char *comboString = malloc( (strlen(array1)+strlen(array2) + 1)*sizeof(char));
comboString = concatenated(array1, array2);
...
The malloc is unnecessary here and actually a bug in your code. You are allocating a block of memory, but you then replace the value of the pointer comboString with the pointer from the call to concatenated. You lose the pointer to the block of memory allocated in main and thus never are able to free it. Although this will not be a problem in the code you have right now since main returns soon after, it could cause a memory leak in an application that ran for a longer time.
strcat(array3, array1);
This is also a bug. strcat is going to walk through array3 to find '\0' and then once it is found copy in array1 from that index on, replacing the '\0'. This works fine here since the memory block that was allocated for array3 is going to be zeroed out** as no block has yet been freed by your program. However, in a longer running program you can end up with a block that does not start with a '\0'. You might end up corrupting your heap, getting a segfault, etc.
To fix this, you should use strcpy instead, array3[0] = '\0', or *array3 = '\0'
** When the operating system starts your program it will initialize the memory segment it reserves for it with zeroes (this actually isn't a necessity but will be true on almost any operating system). As your program allocates and frees memory, you will eventually wind up with values that are not zero. Note that the same bug can occur with uninitialized local variables such as:
int i;
for (; i < 10; i++);
This loop will run 10 times whenever the space on the runtime stack where i is stored is already 0.
Overall, the takeaway is to be very careful with arrays and dynamic memory allocation in C. C offers you none of the protections that modern languages do. You are responsible for making sure you stay within the bounds of your array, initialize your variables, and properly allocate and free your memory. Neglecting these things will lead to obscure bugs that will take you hours to find, and most of the times these bugs will not appear right away.