Possible solutions for returning structs as rvalues without heap allocations: use case neural networks












0















MNIST is the hello world of machine learning and I've practiced it with TensorFlow and with pure python and numpy.



For more practice I am trying to write it in C on my own with only the standard library because I am relatively new to C and it's a great way to learn.



It's taken three weeks, and a lot of SEGFAULTS but I get 81% accuracy. Not very good but it's for learning.



The most troubling stuff was of course malloc/free for the data in the matrix struct as below:



typedef struct matrix{
int rows, cols;
float *data;
} matrix;


The forward and backward passes have things like:



1) matrix dot product
2) matrix add
3) matrix subtract
4) activation function (sigmoid in this case)


To avoid memory leaks I pass in three structs like so:



void matrix_add(matrix *a, matrix *b, matrix *res);


If res requires a dimensions change from a previous layer, then I free it and do a new malloc like so:



void zero_out_data(matrix *res, int rows, int cols)
{
if (res->rows != rows || res->cols != cols)
{
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
free(res);
res = NULL;
res = malloc(sizeof(matrix));
// make_matrix will calloc the data based on rows*cols
// any other init stuff that could be needed
make_matrix(res, rows, cols);
}
res->rows = rows;
res->cols = cols;
}
else {
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}
}


Then I can use that like so:



void sigmoid(matrix *z, matrix *res)
{
zero_out_data(res, z->rows, z->cols);
for (int i = 0; i < (z->rows*z->cols); i++)
{
res->data[i] = 1.0/(1.0+exp(-z->data[i]));
}
}


This gets very messy because a single forward pass has the following:



/* forward pass */
for (int k=0; k < (network->num_layers-1); k++)
{
matrix_dot(network->weights[k], activation, dot);
matrix_add(dot, network->biases[k], zs[k]);
sigmoid(zs[k], activation);
sigmoid(zs[k], activations[k+1]);
}
/* end forward pass */


As you can imagine the backprop gets alot messier. I have to pre-create 8 different matrices, plus many more of those pointers to pointers of matrices like the activations and zs above, for the gradient descent.



What I would like to be able to do is return a matrix from a function like matrix_dot so that I can do:



sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k]));


That's kind of in the style of python/numpy.



Of course I can't return a local variable from a function because it's taken off the stack once the function returns.



If I return a pointer, then the above style will cause sever memory leaks.



Please note: I am not trying to write my own library/framework. I am simply trying to learn neural networks and coding in C. I have been a python developer for 7 years or so, and my C skills need improvement.










share|improve this question























  • Why would you get several memory leaks by returning a pointer ? If you free the memory each time you lose a dynamically allocated address, you should not leak.

    – alamit
    Nov 20 '18 at 3:46











  • If I return a pointer as an rvalue, how can I free it?

    – Sam Hammamy
    Nov 20 '18 at 3:48











  • using the free function, your return value will be the address of the dynamically allocated memory, you can free it as long as you keep the address, even if you pass the address from function to function by rvalue.

    – alamit
    Nov 20 '18 at 3:49











  • Note that free frees memory pointed by a pointer, not the pointer itself.

    – alamit
    Nov 20 '18 at 3:51











  • How can I store the address if I am passing it from function to function? If I store the return value as a variable, it's not any less messier than passing the result into the function.

    – Sam Hammamy
    Nov 20 '18 at 3:51
















0















MNIST is the hello world of machine learning and I've practiced it with TensorFlow and with pure python and numpy.



For more practice I am trying to write it in C on my own with only the standard library because I am relatively new to C and it's a great way to learn.



It's taken three weeks, and a lot of SEGFAULTS but I get 81% accuracy. Not very good but it's for learning.



The most troubling stuff was of course malloc/free for the data in the matrix struct as below:



typedef struct matrix{
int rows, cols;
float *data;
} matrix;


The forward and backward passes have things like:



1) matrix dot product
2) matrix add
3) matrix subtract
4) activation function (sigmoid in this case)


To avoid memory leaks I pass in three structs like so:



void matrix_add(matrix *a, matrix *b, matrix *res);


If res requires a dimensions change from a previous layer, then I free it and do a new malloc like so:



void zero_out_data(matrix *res, int rows, int cols)
{
if (res->rows != rows || res->cols != cols)
{
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
free(res);
res = NULL;
res = malloc(sizeof(matrix));
// make_matrix will calloc the data based on rows*cols
// any other init stuff that could be needed
make_matrix(res, rows, cols);
}
res->rows = rows;
res->cols = cols;
}
else {
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}
}


Then I can use that like so:



void sigmoid(matrix *z, matrix *res)
{
zero_out_data(res, z->rows, z->cols);
for (int i = 0; i < (z->rows*z->cols); i++)
{
res->data[i] = 1.0/(1.0+exp(-z->data[i]));
}
}


This gets very messy because a single forward pass has the following:



/* forward pass */
for (int k=0; k < (network->num_layers-1); k++)
{
matrix_dot(network->weights[k], activation, dot);
matrix_add(dot, network->biases[k], zs[k]);
sigmoid(zs[k], activation);
sigmoid(zs[k], activations[k+1]);
}
/* end forward pass */


As you can imagine the backprop gets alot messier. I have to pre-create 8 different matrices, plus many more of those pointers to pointers of matrices like the activations and zs above, for the gradient descent.



What I would like to be able to do is return a matrix from a function like matrix_dot so that I can do:



sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k]));


That's kind of in the style of python/numpy.



Of course I can't return a local variable from a function because it's taken off the stack once the function returns.



If I return a pointer, then the above style will cause sever memory leaks.



Please note: I am not trying to write my own library/framework. I am simply trying to learn neural networks and coding in C. I have been a python developer for 7 years or so, and my C skills need improvement.










share|improve this question























  • Why would you get several memory leaks by returning a pointer ? If you free the memory each time you lose a dynamically allocated address, you should not leak.

    – alamit
    Nov 20 '18 at 3:46











  • If I return a pointer as an rvalue, how can I free it?

    – Sam Hammamy
    Nov 20 '18 at 3:48











  • using the free function, your return value will be the address of the dynamically allocated memory, you can free it as long as you keep the address, even if you pass the address from function to function by rvalue.

    – alamit
    Nov 20 '18 at 3:49











  • Note that free frees memory pointed by a pointer, not the pointer itself.

    – alamit
    Nov 20 '18 at 3:51











  • How can I store the address if I am passing it from function to function? If I store the return value as a variable, it's not any less messier than passing the result into the function.

    – Sam Hammamy
    Nov 20 '18 at 3:51














0












0








0








MNIST is the hello world of machine learning and I've practiced it with TensorFlow and with pure python and numpy.



For more practice I am trying to write it in C on my own with only the standard library because I am relatively new to C and it's a great way to learn.



It's taken three weeks, and a lot of SEGFAULTS but I get 81% accuracy. Not very good but it's for learning.



The most troubling stuff was of course malloc/free for the data in the matrix struct as below:



typedef struct matrix{
int rows, cols;
float *data;
} matrix;


The forward and backward passes have things like:



1) matrix dot product
2) matrix add
3) matrix subtract
4) activation function (sigmoid in this case)


To avoid memory leaks I pass in three structs like so:



void matrix_add(matrix *a, matrix *b, matrix *res);


If res requires a dimensions change from a previous layer, then I free it and do a new malloc like so:



void zero_out_data(matrix *res, int rows, int cols)
{
if (res->rows != rows || res->cols != cols)
{
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
free(res);
res = NULL;
res = malloc(sizeof(matrix));
// make_matrix will calloc the data based on rows*cols
// any other init stuff that could be needed
make_matrix(res, rows, cols);
}
res->rows = rows;
res->cols = cols;
}
else {
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}
}


Then I can use that like so:



void sigmoid(matrix *z, matrix *res)
{
zero_out_data(res, z->rows, z->cols);
for (int i = 0; i < (z->rows*z->cols); i++)
{
res->data[i] = 1.0/(1.0+exp(-z->data[i]));
}
}


This gets very messy because a single forward pass has the following:



/* forward pass */
for (int k=0; k < (network->num_layers-1); k++)
{
matrix_dot(network->weights[k], activation, dot);
matrix_add(dot, network->biases[k], zs[k]);
sigmoid(zs[k], activation);
sigmoid(zs[k], activations[k+1]);
}
/* end forward pass */


As you can imagine the backprop gets alot messier. I have to pre-create 8 different matrices, plus many more of those pointers to pointers of matrices like the activations and zs above, for the gradient descent.



What I would like to be able to do is return a matrix from a function like matrix_dot so that I can do:



sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k]));


That's kind of in the style of python/numpy.



Of course I can't return a local variable from a function because it's taken off the stack once the function returns.



If I return a pointer, then the above style will cause sever memory leaks.



Please note: I am not trying to write my own library/framework. I am simply trying to learn neural networks and coding in C. I have been a python developer for 7 years or so, and my C skills need improvement.










share|improve this question














MNIST is the hello world of machine learning and I've practiced it with TensorFlow and with pure python and numpy.



For more practice I am trying to write it in C on my own with only the standard library because I am relatively new to C and it's a great way to learn.



It's taken three weeks, and a lot of SEGFAULTS but I get 81% accuracy. Not very good but it's for learning.



The most troubling stuff was of course malloc/free for the data in the matrix struct as below:



typedef struct matrix{
int rows, cols;
float *data;
} matrix;


The forward and backward passes have things like:



1) matrix dot product
2) matrix add
3) matrix subtract
4) activation function (sigmoid in this case)


To avoid memory leaks I pass in three structs like so:



void matrix_add(matrix *a, matrix *b, matrix *res);


If res requires a dimensions change from a previous layer, then I free it and do a new malloc like so:



void zero_out_data(matrix *res, int rows, int cols)
{
if (res->rows != rows || res->cols != cols)
{
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
free(res);
res = NULL;
res = malloc(sizeof(matrix));
// make_matrix will calloc the data based on rows*cols
// any other init stuff that could be needed
make_matrix(res, rows, cols);
}
res->rows = rows;
res->cols = cols;
}
else {
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}
}


Then I can use that like so:



void sigmoid(matrix *z, matrix *res)
{
zero_out_data(res, z->rows, z->cols);
for (int i = 0; i < (z->rows*z->cols); i++)
{
res->data[i] = 1.0/(1.0+exp(-z->data[i]));
}
}


This gets very messy because a single forward pass has the following:



/* forward pass */
for (int k=0; k < (network->num_layers-1); k++)
{
matrix_dot(network->weights[k], activation, dot);
matrix_add(dot, network->biases[k], zs[k]);
sigmoid(zs[k], activation);
sigmoid(zs[k], activations[k+1]);
}
/* end forward pass */


As you can imagine the backprop gets alot messier. I have to pre-create 8 different matrices, plus many more of those pointers to pointers of matrices like the activations and zs above, for the gradient descent.



What I would like to be able to do is return a matrix from a function like matrix_dot so that I can do:



sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k]));


That's kind of in the style of python/numpy.



Of course I can't return a local variable from a function because it's taken off the stack once the function returns.



If I return a pointer, then the above style will cause sever memory leaks.



Please note: I am not trying to write my own library/framework. I am simply trying to learn neural networks and coding in C. I have been a python developer for 7 years or so, and my C skills need improvement.







python c neural-network malloc rvalue






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 '18 at 3:36









Sam HammamySam Hammamy

4,06572766




4,06572766













  • Why would you get several memory leaks by returning a pointer ? If you free the memory each time you lose a dynamically allocated address, you should not leak.

    – alamit
    Nov 20 '18 at 3:46











  • If I return a pointer as an rvalue, how can I free it?

    – Sam Hammamy
    Nov 20 '18 at 3:48











  • using the free function, your return value will be the address of the dynamically allocated memory, you can free it as long as you keep the address, even if you pass the address from function to function by rvalue.

    – alamit
    Nov 20 '18 at 3:49











  • Note that free frees memory pointed by a pointer, not the pointer itself.

    – alamit
    Nov 20 '18 at 3:51











  • How can I store the address if I am passing it from function to function? If I store the return value as a variable, it's not any less messier than passing the result into the function.

    – Sam Hammamy
    Nov 20 '18 at 3:51



















  • Why would you get several memory leaks by returning a pointer ? If you free the memory each time you lose a dynamically allocated address, you should not leak.

    – alamit
    Nov 20 '18 at 3:46











  • If I return a pointer as an rvalue, how can I free it?

    – Sam Hammamy
    Nov 20 '18 at 3:48











  • using the free function, your return value will be the address of the dynamically allocated memory, you can free it as long as you keep the address, even if you pass the address from function to function by rvalue.

    – alamit
    Nov 20 '18 at 3:49











  • Note that free frees memory pointed by a pointer, not the pointer itself.

    – alamit
    Nov 20 '18 at 3:51











  • How can I store the address if I am passing it from function to function? If I store the return value as a variable, it's not any less messier than passing the result into the function.

    – Sam Hammamy
    Nov 20 '18 at 3:51

















Why would you get several memory leaks by returning a pointer ? If you free the memory each time you lose a dynamically allocated address, you should not leak.

– alamit
Nov 20 '18 at 3:46





Why would you get several memory leaks by returning a pointer ? If you free the memory each time you lose a dynamically allocated address, you should not leak.

– alamit
Nov 20 '18 at 3:46













If I return a pointer as an rvalue, how can I free it?

– Sam Hammamy
Nov 20 '18 at 3:48





If I return a pointer as an rvalue, how can I free it?

– Sam Hammamy
Nov 20 '18 at 3:48













using the free function, your return value will be the address of the dynamically allocated memory, you can free it as long as you keep the address, even if you pass the address from function to function by rvalue.

– alamit
Nov 20 '18 at 3:49





using the free function, your return value will be the address of the dynamically allocated memory, you can free it as long as you keep the address, even if you pass the address from function to function by rvalue.

– alamit
Nov 20 '18 at 3:49













Note that free frees memory pointed by a pointer, not the pointer itself.

– alamit
Nov 20 '18 at 3:51





Note that free frees memory pointed by a pointer, not the pointer itself.

– alamit
Nov 20 '18 at 3:51













How can I store the address if I am passing it from function to function? If I store the return value as a variable, it's not any less messier than passing the result into the function.

– Sam Hammamy
Nov 20 '18 at 3:51





How can I store the address if I am passing it from function to function? If I store the return value as a variable, it's not any less messier than passing the result into the function.

– Sam Hammamy
Nov 20 '18 at 3:51












1 Answer
1






active

oldest

votes


















0














Memory leak in void zero_out_data(matrix *res, int rows, int cols)



matrix *res malloc out of the function and pass to zero_out_data. In zero_out_data, res is free and malloc again. If you want to change pointer res's value, then you need parameter like matrix **res.



If you want zero out data, no need malloc new matrix, just malloc the data part. I think your make_matrix function can malloc memory for data.



void zero_out_data(matrix *res, int rows, int col) {
if (res->data == NULL) {
make_matrix(res, rows, cols);
} else if (res->rows != rows || res->cols != cols) {
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
make_matrix(res, rows, cols);
}
}
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}


How to implement this: sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k])); ?



You can use static or global variables to implement what you want. This will not be thread safe and reentrant. Examples in below:



matrix *matrix_dot(matrix *in_a, matrix *in_b)
{
static matrix res = {0, 0, NULL}; // static variable

// calculate the res's cols and rows number
zero_out_data(&res, res_cols, res_rows); // malloc new data

// do some math.

return &res;
}

// matrix_add will be just like matrix_dot

// I was wrong about sigmod no need new matrix. sigmod can also do it like matrix_dot.


You can use global variable replace static variable.



If you want thread-safe or reentrant, then just use local variable, then you can do it like this.



matrix *matrix_dot(matrix *in_a, matrix *in_b, matrix *res) 
{
zero_out_data(res, xxx, xxx);
// do some math
return res;
}
// matrix_add will be the same.

// define local variables.
matrix add_res, dot_res, sig_res;
add_res->data = NULL;
dot_res->data = NULL;
sig_res->data = NULL;

sigmod(matrix_add(matrix_dot(network->weights[k], activation, &dot_res), network->biases[k], &add_res), &sig_res)

// Now remember to free data in matrix
free(add_res->data);
free(dot_res->data);
free(sig_res->data);





share|improve this answer


























  • If I'm not mistaken,static could cause trouble later on right?

    – Sam Hammamy
    Nov 20 '18 at 5:14













  • Good point about no need for malloc the matrix again, only the data!

    – Sam Hammamy
    Nov 20 '18 at 5:16











  • @SamHammamy If no need thread-safe, then static will just contain memory not free until program ends. When use local variable, you need to pass the result, unless you can store your result in parameter. Like add(int *a, int *b), after add result stores in a. I'm not sure about this in your case.

    – Xianggang ZENG
    Nov 20 '18 at 5:18











  • thanks! I am thinking about creating a new matrix in each of those matrix_dot, matrix_add, sigmoid, etc, then adding a flag to the struct for can_free = 0, so I can just free the two inputs if they're not need later, and return a pointer from the functions. The assumption is each pointer returned from those functions can be freed when it becomes an input to another one. Hopefully this pans out

    – Sam Hammamy
    Nov 20 '18 at 5:24











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385851%2fpossible-solutions-for-returning-structs-as-rvalues-without-heap-allocations-us%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Memory leak in void zero_out_data(matrix *res, int rows, int cols)



matrix *res malloc out of the function and pass to zero_out_data. In zero_out_data, res is free and malloc again. If you want to change pointer res's value, then you need parameter like matrix **res.



If you want zero out data, no need malloc new matrix, just malloc the data part. I think your make_matrix function can malloc memory for data.



void zero_out_data(matrix *res, int rows, int col) {
if (res->data == NULL) {
make_matrix(res, rows, cols);
} else if (res->rows != rows || res->cols != cols) {
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
make_matrix(res, rows, cols);
}
}
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}


How to implement this: sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k])); ?



You can use static or global variables to implement what you want. This will not be thread safe and reentrant. Examples in below:



matrix *matrix_dot(matrix *in_a, matrix *in_b)
{
static matrix res = {0, 0, NULL}; // static variable

// calculate the res's cols and rows number
zero_out_data(&res, res_cols, res_rows); // malloc new data

// do some math.

return &res;
}

// matrix_add will be just like matrix_dot

// I was wrong about sigmod no need new matrix. sigmod can also do it like matrix_dot.


You can use global variable replace static variable.



If you want thread-safe or reentrant, then just use local variable, then you can do it like this.



matrix *matrix_dot(matrix *in_a, matrix *in_b, matrix *res) 
{
zero_out_data(res, xxx, xxx);
// do some math
return res;
}
// matrix_add will be the same.

// define local variables.
matrix add_res, dot_res, sig_res;
add_res->data = NULL;
dot_res->data = NULL;
sig_res->data = NULL;

sigmod(matrix_add(matrix_dot(network->weights[k], activation, &dot_res), network->biases[k], &add_res), &sig_res)

// Now remember to free data in matrix
free(add_res->data);
free(dot_res->data);
free(sig_res->data);





share|improve this answer


























  • If I'm not mistaken,static could cause trouble later on right?

    – Sam Hammamy
    Nov 20 '18 at 5:14













  • Good point about no need for malloc the matrix again, only the data!

    – Sam Hammamy
    Nov 20 '18 at 5:16











  • @SamHammamy If no need thread-safe, then static will just contain memory not free until program ends. When use local variable, you need to pass the result, unless you can store your result in parameter. Like add(int *a, int *b), after add result stores in a. I'm not sure about this in your case.

    – Xianggang ZENG
    Nov 20 '18 at 5:18











  • thanks! I am thinking about creating a new matrix in each of those matrix_dot, matrix_add, sigmoid, etc, then adding a flag to the struct for can_free = 0, so I can just free the two inputs if they're not need later, and return a pointer from the functions. The assumption is each pointer returned from those functions can be freed when it becomes an input to another one. Hopefully this pans out

    – Sam Hammamy
    Nov 20 '18 at 5:24
















0














Memory leak in void zero_out_data(matrix *res, int rows, int cols)



matrix *res malloc out of the function and pass to zero_out_data. In zero_out_data, res is free and malloc again. If you want to change pointer res's value, then you need parameter like matrix **res.



If you want zero out data, no need malloc new matrix, just malloc the data part. I think your make_matrix function can malloc memory for data.



void zero_out_data(matrix *res, int rows, int col) {
if (res->data == NULL) {
make_matrix(res, rows, cols);
} else if (res->rows != rows || res->cols != cols) {
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
make_matrix(res, rows, cols);
}
}
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}


How to implement this: sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k])); ?



You can use static or global variables to implement what you want. This will not be thread safe and reentrant. Examples in below:



matrix *matrix_dot(matrix *in_a, matrix *in_b)
{
static matrix res = {0, 0, NULL}; // static variable

// calculate the res's cols and rows number
zero_out_data(&res, res_cols, res_rows); // malloc new data

// do some math.

return &res;
}

// matrix_add will be just like matrix_dot

// I was wrong about sigmod no need new matrix. sigmod can also do it like matrix_dot.


You can use global variable replace static variable.



If you want thread-safe or reentrant, then just use local variable, then you can do it like this.



matrix *matrix_dot(matrix *in_a, matrix *in_b, matrix *res) 
{
zero_out_data(res, xxx, xxx);
// do some math
return res;
}
// matrix_add will be the same.

// define local variables.
matrix add_res, dot_res, sig_res;
add_res->data = NULL;
dot_res->data = NULL;
sig_res->data = NULL;

sigmod(matrix_add(matrix_dot(network->weights[k], activation, &dot_res), network->biases[k], &add_res), &sig_res)

// Now remember to free data in matrix
free(add_res->data);
free(dot_res->data);
free(sig_res->data);





share|improve this answer


























  • If I'm not mistaken,static could cause trouble later on right?

    – Sam Hammamy
    Nov 20 '18 at 5:14













  • Good point about no need for malloc the matrix again, only the data!

    – Sam Hammamy
    Nov 20 '18 at 5:16











  • @SamHammamy If no need thread-safe, then static will just contain memory not free until program ends. When use local variable, you need to pass the result, unless you can store your result in parameter. Like add(int *a, int *b), after add result stores in a. I'm not sure about this in your case.

    – Xianggang ZENG
    Nov 20 '18 at 5:18











  • thanks! I am thinking about creating a new matrix in each of those matrix_dot, matrix_add, sigmoid, etc, then adding a flag to the struct for can_free = 0, so I can just free the two inputs if they're not need later, and return a pointer from the functions. The assumption is each pointer returned from those functions can be freed when it becomes an input to another one. Hopefully this pans out

    – Sam Hammamy
    Nov 20 '18 at 5:24














0












0








0







Memory leak in void zero_out_data(matrix *res, int rows, int cols)



matrix *res malloc out of the function and pass to zero_out_data. In zero_out_data, res is free and malloc again. If you want to change pointer res's value, then you need parameter like matrix **res.



If you want zero out data, no need malloc new matrix, just malloc the data part. I think your make_matrix function can malloc memory for data.



void zero_out_data(matrix *res, int rows, int col) {
if (res->data == NULL) {
make_matrix(res, rows, cols);
} else if (res->rows != rows || res->cols != cols) {
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
make_matrix(res, rows, cols);
}
}
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}


How to implement this: sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k])); ?



You can use static or global variables to implement what you want. This will not be thread safe and reentrant. Examples in below:



matrix *matrix_dot(matrix *in_a, matrix *in_b)
{
static matrix res = {0, 0, NULL}; // static variable

// calculate the res's cols and rows number
zero_out_data(&res, res_cols, res_rows); // malloc new data

// do some math.

return &res;
}

// matrix_add will be just like matrix_dot

// I was wrong about sigmod no need new matrix. sigmod can also do it like matrix_dot.


You can use global variable replace static variable.



If you want thread-safe or reentrant, then just use local variable, then you can do it like this.



matrix *matrix_dot(matrix *in_a, matrix *in_b, matrix *res) 
{
zero_out_data(res, xxx, xxx);
// do some math
return res;
}
// matrix_add will be the same.

// define local variables.
matrix add_res, dot_res, sig_res;
add_res->data = NULL;
dot_res->data = NULL;
sig_res->data = NULL;

sigmod(matrix_add(matrix_dot(network->weights[k], activation, &dot_res), network->biases[k], &add_res), &sig_res)

// Now remember to free data in matrix
free(add_res->data);
free(dot_res->data);
free(sig_res->data);





share|improve this answer















Memory leak in void zero_out_data(matrix *res, int rows, int cols)



matrix *res malloc out of the function and pass to zero_out_data. In zero_out_data, res is free and malloc again. If you want to change pointer res's value, then you need parameter like matrix **res.



If you want zero out data, no need malloc new matrix, just malloc the data part. I think your make_matrix function can malloc memory for data.



void zero_out_data(matrix *res, int rows, int col) {
if (res->data == NULL) {
make_matrix(res, rows, cols);
} else if (res->rows != rows || res->cols != cols) {
if ((res->rows*res->cols) != (rows*cols))
{
free(res->data);
res->data = NULL;
make_matrix(res, rows, cols);
}
}
res->rows = rows;
res->cols = cols;
for (int i =0; i < (rows*cols); i++)
{
res->data[i] = 0.0;
}
}


How to implement this: sigmoid(matrix_add(matrix_dot(network->weights[k], activation), network->biases[k])); ?



You can use static or global variables to implement what you want. This will not be thread safe and reentrant. Examples in below:



matrix *matrix_dot(matrix *in_a, matrix *in_b)
{
static matrix res = {0, 0, NULL}; // static variable

// calculate the res's cols and rows number
zero_out_data(&res, res_cols, res_rows); // malloc new data

// do some math.

return &res;
}

// matrix_add will be just like matrix_dot

// I was wrong about sigmod no need new matrix. sigmod can also do it like matrix_dot.


You can use global variable replace static variable.



If you want thread-safe or reentrant, then just use local variable, then you can do it like this.



matrix *matrix_dot(matrix *in_a, matrix *in_b, matrix *res) 
{
zero_out_data(res, xxx, xxx);
// do some math
return res;
}
// matrix_add will be the same.

// define local variables.
matrix add_res, dot_res, sig_res;
add_res->data = NULL;
dot_res->data = NULL;
sig_res->data = NULL;

sigmod(matrix_add(matrix_dot(network->weights[k], activation, &dot_res), network->biases[k], &add_res), &sig_res)

// Now remember to free data in matrix
free(add_res->data);
free(dot_res->data);
free(sig_res->data);






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 20 '18 at 5:55

























answered Nov 20 '18 at 5:06









Xianggang ZENGXianggang ZENG

30129




30129













  • If I'm not mistaken,static could cause trouble later on right?

    – Sam Hammamy
    Nov 20 '18 at 5:14













  • Good point about no need for malloc the matrix again, only the data!

    – Sam Hammamy
    Nov 20 '18 at 5:16











  • @SamHammamy If no need thread-safe, then static will just contain memory not free until program ends. When use local variable, you need to pass the result, unless you can store your result in parameter. Like add(int *a, int *b), after add result stores in a. I'm not sure about this in your case.

    – Xianggang ZENG
    Nov 20 '18 at 5:18











  • thanks! I am thinking about creating a new matrix in each of those matrix_dot, matrix_add, sigmoid, etc, then adding a flag to the struct for can_free = 0, so I can just free the two inputs if they're not need later, and return a pointer from the functions. The assumption is each pointer returned from those functions can be freed when it becomes an input to another one. Hopefully this pans out

    – Sam Hammamy
    Nov 20 '18 at 5:24



















  • If I'm not mistaken,static could cause trouble later on right?

    – Sam Hammamy
    Nov 20 '18 at 5:14













  • Good point about no need for malloc the matrix again, only the data!

    – Sam Hammamy
    Nov 20 '18 at 5:16











  • @SamHammamy If no need thread-safe, then static will just contain memory not free until program ends. When use local variable, you need to pass the result, unless you can store your result in parameter. Like add(int *a, int *b), after add result stores in a. I'm not sure about this in your case.

    – Xianggang ZENG
    Nov 20 '18 at 5:18











  • thanks! I am thinking about creating a new matrix in each of those matrix_dot, matrix_add, sigmoid, etc, then adding a flag to the struct for can_free = 0, so I can just free the two inputs if they're not need later, and return a pointer from the functions. The assumption is each pointer returned from those functions can be freed when it becomes an input to another one. Hopefully this pans out

    – Sam Hammamy
    Nov 20 '18 at 5:24

















If I'm not mistaken,static could cause trouble later on right?

– Sam Hammamy
Nov 20 '18 at 5:14







If I'm not mistaken,static could cause trouble later on right?

– Sam Hammamy
Nov 20 '18 at 5:14















Good point about no need for malloc the matrix again, only the data!

– Sam Hammamy
Nov 20 '18 at 5:16





Good point about no need for malloc the matrix again, only the data!

– Sam Hammamy
Nov 20 '18 at 5:16













@SamHammamy If no need thread-safe, then static will just contain memory not free until program ends. When use local variable, you need to pass the result, unless you can store your result in parameter. Like add(int *a, int *b), after add result stores in a. I'm not sure about this in your case.

– Xianggang ZENG
Nov 20 '18 at 5:18





@SamHammamy If no need thread-safe, then static will just contain memory not free until program ends. When use local variable, you need to pass the result, unless you can store your result in parameter. Like add(int *a, int *b), after add result stores in a. I'm not sure about this in your case.

– Xianggang ZENG
Nov 20 '18 at 5:18













thanks! I am thinking about creating a new matrix in each of those matrix_dot, matrix_add, sigmoid, etc, then adding a flag to the struct for can_free = 0, so I can just free the two inputs if they're not need later, and return a pointer from the functions. The assumption is each pointer returned from those functions can be freed when it becomes an input to another one. Hopefully this pans out

– Sam Hammamy
Nov 20 '18 at 5:24





thanks! I am thinking about creating a new matrix in each of those matrix_dot, matrix_add, sigmoid, etc, then adding a flag to the struct for can_free = 0, so I can just free the two inputs if they're not need later, and return a pointer from the functions. The assumption is each pointer returned from those functions can be freed when it becomes an input to another one. Hopefully this pans out

– Sam Hammamy
Nov 20 '18 at 5:24




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385851%2fpossible-solutions-for-returning-structs-as-rvalues-without-heap-allocations-us%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Tangent Lines Diagram Along Smooth Curve

Yusuf al-Mu'taman ibn Hud

Zucchini