I'm using the asn1c lib for many projects, but I never found how to use the free member of a SEQUENCE_OF. I always set it to nullptr because of that, and when I use Valgrind, I see (of course) that my lists members are not freed when using ASN_STRUCT_FREE on the element containing the list.
So my question is how can I use that free member?
Here is a simple example of how I use my lists with asn1c.
ListItem_t *li = nullptr;
StructWList_t swl;
swl.list.count = 0;
swl.list.size = 0;
swl.list.free = nullptr; // How can I feed it properly?
swl.list.array = reinterpret_cast<ListItem_t**>(calloc(1, sizeof *swl.list.array));
for(int i = 0 ; i < 5 ; i++)
{
li = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *li));
*li = i;
// Valgrind says that the calloc below is definitly lost
swl.list.array[i] = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *swl.list.array[i]));
ASN_SEQUENCE_ADD(&swl, li);
}
...
ASN_STRUCT_FREE(ASN_DEF_StructWList, &swl);
Does anyone know how to feed it properly?
EDIT
My version of asn1c is the v0.9.29 from git repository in AUR (on Archlinux).
The above ASN.1 is as follow:
Example
DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
StructWList ::= SEQUENCE OF ListItem
ListItem ::= INTEGER
END
Thanks in advance,
Emilien
// Valgrind says that the calloc below is definitly lost
swl.list.array[i] = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *swl.list.array[i]));
ASN_SEQUENCE_ADD(&swl, li);
The ASN_SEQUENCE_ADD will overwrite the pointer you stored on the previous line. You should either store it manually as on the first line or call ASN_SEQUENCE_ADD but not both.
Also you should fully initialize swl as it contains more members (_asn_ctx) and use ASN_STRUCT_FREE_CONTENTS_ONLY as swl is allocated on the stack and cannot be freed.
--- main.cpp.orig 2019-05-07 20:49:25.880336931 +0300
+++ main.cpp 2019-05-07 20:59:10.192431926 +0300
## -3,7 +3,7 ##
int main()
{
ListItem_t *li = nullptr;
- StructWList_t swl;
+ StructWList_t swl = {0};
swl.list.count = 0;
swl.list.size = 0;
## -15,8 +15,8 ##
li = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *li));
*li = i;
// Valgrind says that the calloc below is definitly lost
- swl.list.array[i] = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *swl.list.array[i]));
+ //swl.list.array[i] = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *swl.list.array[i]));
ASN_SEQUENCE_ADD(&swl, li);
}
- ASN_STRUCT_FREE(ASN_DEF_StructWList, &swl);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_StructWList, &swl);
}
Compile with g++ -Wall -I. -ggdb -O0 -o test main.cpp libasncodec.a
valgrind --tool=memcheck ./test
==29555== Memcheck, a memory error detector
==29555== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29555== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==29555== Command: ./test
==29555==
==29555==
==29555== HEAP SUMMARY:
==29555== in use at exit: 0 bytes in 0 blocks
==29555== total heap usage: 9 allocs, 9 frees, 72,848 bytes allocated
==29555==
==29555== All heap blocks were freed -- no leaks are possible
==29555==
==29555== For counts of detected and suppressed errors, rerun with: -v
==29555== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Related
I run my program using valgrind like this:
valgrind --leak-check=full ./a.out < in0.txt > out0.txt
and get the following output:
==13077== Memcheck, a memory error detector
==13077== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==13077== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==13077== Command: ./a.out
==13077==
==13077== Conditional jump or move depends on uninitialised value(s)
==13077== at 0x40491F: OnGetMostViewedClasses (in /home/user/a.out)
==13077== by 0x404498: parser (in /home/user/a.out)
==13077== by 0x404263: main (in /home/user/a.out)
==13077==
==13077==
==13077== HEAP SUMMARY:
==13077== in use at exit: 0 bytes in 0 blocks
==13077== total heap usage: 90 allocs, 90 frees, 6,200 bytes allocated
==13077==
==13077== All heap blocks were freed -- no leaks are possible
==13077==
==13077== For counts of detected and suppressed errors, rerun with: -v
==13077== Use --track-origins=yes to see where uninitialised values come from
==13077== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
-bash-4.2$
while it refers to StatusType res; used in here:
static errorType OnGetMostViewedClasses(void* DS, const char* const command) {
int numOfClasses;
int *courses = NULL, *classes = NULL;
StatusType res;
ValidateRead(sscanf(command, "%d", &numOfClasses), 1, "%s failed.\n", commandStr[GETMOSTVIEWEDCLASSES_CMD]);
if (numOfClasses > 0) {
courses = (int *)malloc(numOfClasses * sizeof(int));
classes = (int *)malloc(numOfClasses * sizeof(int));
if (courses == NULL || classes == NULL) {
res = ALLOCATION_ERROR;
}
}
if (res != ALLOCATION_ERROR) {
res = GetMostViewedClasses(DS, numOfClasses, courses, classes);
}
if (res != SUCCESS) {
printf("%s: %s\n", commandStr[GETMOSTVIEWEDCLASSES_CMD], ReturnValToStr(res));
if (courses != NULL) free(courses);
if (classes != NULL) free(classes);
return error_free;
}
printf("%s: %s\n", commandStr[GETMOSTVIEWEDCLASSES_CMD], ReturnValToStr(res));
printf("Course\t|\tClass\n");
for (int i = 0; i < numOfClasses; i++)
{
printf("%d\t|\t%d\n", courses[i], classes[i]);
}
printf("--End of most viewed classes--\n");
if (courses != NULL) free(courses);
if (classes != NULL) free(classes);
return error_free;
}
and declared like this:
typedef enum {
SUCCESS = 0,
FAILURE = -1,
ALLOCATION_ERROR = -2,
INVALID_INPUT = -3
} StatusType;
So my question is, how can I solve this problem without changing the above code since it was given to us and my professor told: "you aren't allowed to change it" and "any errors found by valgrind will get you a mark of 0"?
Any ideas or suggestions are welcomed.
please note: except this problem I have 0 memory leak issue (According to 32 input files I tested)
Neither res nor numOfClasses is initialized. There are code paths that can result in these values being used in if statements without having a value assigned to them. scanf can fail, leaving numOfClasses uninitialized, and unless an error occurs in memory allocation res will not be assigned a value.
The solution is to initialize both:
int numOfClasses = 0;
StatusType res = SUCCESS;
As #1201ProgramAlarm points out, res is not initialized, and since it only gets set if numOfClasses is greater than zero and one of the malloc calls fails, you would need to somehow force the code into that code path. So, make sure the sscanf reads a value from command (command should be "1" or something like that), and then ... somehow cause malloc to return NULL. That's not trivial, but maybe you can add a clever line like #define malloc(x) NULL somewhere above that function? This entire exercise seems pretty terrible, TBH.
Edit: Alternatively, make malloc fail by asking for TOO MUCH memory. If numOfClasses is something like SIZE_MAX/sizeof(int), there's a pretty good chance you won't be able to allocate two blocks of memory that big, and one or both malloc calls will return NULL. That sets the res variable, and there won't be an uninitialized read. Stupid, stupid, stupid.
This is tagged C++, but the code, with typedef enum, void*, malloc, printf and scanf smells badly of C. That is not a good way to learn C++.
You don't provide a definition of ValidateRead. You might just be able to subvert the preprocessor to do what you need, but this will be tortuous.
What the code really should do is res = ValidateRead(... where ValidateRead is a function that returns SUCCESS or INVALID_INPUT.
I am trying to submit my solution on leetcode, when I submit it it gives me a run time error.
AddressSanitizer: stack-buffer-overflow on address 0x7ffd6484f411 at pc 0x000000386795 bp 0x7ffd6484ed70 sp 0x7ffd6484ed68
Here is my code:
int lengthOfLongestSubstring(std::string s)
{
auto start = std::begin(s);
std::string substring = std::string(std::begin(s), std::begin(s) + 1);
std::string pre_string = std::string(std::begin(s), std::begin(s) + 1);
for (auto itr = std::begin(s) + 1; itr != std::end(s); ++itr)
{
auto next = itr;
if (std::find(std::begin(substring), std::end(substring), *itr) ==
std::end(substring))
{
substring = std::string(start, itr + 1);
}
else
{
if (++next != std::end(s))
{
start = itr;
pre_string = substring;
substring = std::string(itr, ++itr);
}
}
}
if (pre_string.length() > substring.length())
{
return pre_string.length();
}
else
return substring.length();
}
when I try to run it on my machine, It does not give me any warning. It's running totally fine.
I am using the following command.
g++ -Wall -Wpedantic longestString.cpp -o long.o
and further I used valgrind to see the any problem but it also says there is no problem as you can see the output.
username#droozal:~/leetcode$ valgrind ./long.o
==9473== Memcheck, a memory error detector
==9473== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9473== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9473== Command: ./long.o
==9473==
5
==9473==
==9473== HEAP SUMMARY:
==9473== in use at exit: 0 bytes in 0 blocks
==9473== total heap usage: 2 allocs, 2 frees, 73,728 bytes allocated
==9473==
==9473== All heap blocks were freed -- no leaks are possible
==9473==
==9473== For counts of detected and suppressed errors, rerun with: -v
==9473== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
so my question is what can be the potential error? is something broken in my code Or what? Answers will be appreciated. Thanks.
I see that you're trying to solve with constant memory, I guess. You can use memoization though for this problem, much simpler to code/debug.
This'll pass through:
#include <string>
#include <map>
#include <algorithm>
class Solution {
public:
static inline int lengthOfLongestSubstring(const std::string s) {
map<char, int> char_map;
int start = -1;
int longest = 0;
const int length = s.size();
for (int index = 0; index < length; index++) {
if (char_map.count(s[index]) != 0) {
start = std::max(start, char_map[s[index]]);
}
char_map[s[index]] = index;
longest = std::max(longest, index - start);
}
return longest;
}
};
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.
I'm confused as to how deallocating vector memory works.
For the example below,
vector<Object*> vec;
for(int i = 0; i < 10; i++){
Object* obj = new Object();
vec.push_pack(obj);
}
//DEALLOCATE CODE HERE//
What should I do to deallocate vec properly?
The program seems to run fine as it is but I'm not sure.
avoid using new/delete :
std::vector<std::unique_ptr<Object>> vec;
for(int i = 0; i < 10; i++)
{
vec.push_pack(std::make_unique<Object>());
}
the unique_ptr will take care of deletion
how deallocating
for instance do
for(auto o : vect){
delete o;
}
vect.clear();
Note you written push_pack rather than push_back to fill the vector
making a full program :
#include <vector>
using namespace std;
class Object{};
int main()
{
vector<Object*> vec;
for(int i = 0; i < 10; i++){
Object* obj = new Object();
vec.push_back(obj);
}
for(auto o : vec){
delete o;
}
vec.clear();
}
Compilation and execution under valgrind :
pi#raspberrypi:/tmp $ g++ v.cc
pi#raspberrypi:/tmp $ valgrind ./a.out
==9157== Memcheck, a memory error detector
==9157== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9157== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9157== Command: ./a.out
==9157==
==9157==
==9157== HEAP SUMMARY:
==9157== in use at exit: 0 bytes in 0 blocks
==9157== total heap usage: 16 allocs, 16 frees, 20,358 bytes allocated
==9157==
==9157== All heap blocks were freed -- no leaks are possible
==9157==
==9157== For counts of detected and suppressed errors, rerun with: -v
==9157== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
all allocated memory was freed
I am learning to create array of pointer and free up memory. This is my simple code
#include <iostream>
using namespace std;
int main()
{
int* classroom[5];
for (int i = 0; i < 5; i++) {
classroom[i] = new int;
}
for (int i = 0; i < 5; i++) {
classroom[i] = &i;
cout<<*classroom[i]<<endl;
}
for (int i = 0; i < 5; i++) {
delete classroom[i];
}
return 0;
}
When I run in valgrind to check for the memory leak, this is the result
==2868== Memcheck, a memory error detector
==2868== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==2868== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==2868== Command: ./m
==2868==
0
1
2
3
4
==2868== Invalid free() / delete / delete[] / realloc()
==2868== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2868== by 0x8048700: main (in /home/student/Downloads/demo/m)
==2868== Address 0xbea69244 is on thread 1's stack
==2868==
==2868==
==2868== HEAP SUMMARY:
==2868== in use at exit: 20 bytes in 5 blocks
==2868== total heap usage: 5 allocs, 5 frees, 20 bytes allocated
==2868==
==2868== LEAK SUMMARY:
==2868== definitely lost: 20 bytes in 5 blocks
==2868== indirectly lost: 0 bytes in 0 blocks
==2868== possibly lost: 0 bytes in 0 blocks
==2868== still reachable: 0 bytes in 0 blocks
==2868== suppressed: 0 bytes in 0 blocks
==2868== Rerun with --leak-check=full to see details of leaked memory
==2868==
==2868== For counts of detected and suppressed errors, rerun with: -v
==2868== ERROR SUMMARY: 5 errors from 1 contexts (suppressed: 0 from 0)
My question is, why I have received the message "invalid free()/delete/delete[]/realloc[]" ? and how to fix it ?
Thanks,
classroom[i] = &i;
should be:
*classroom[i] = i;
You're replacing the pointer that you allocated with new with the address of the local variable i. Then you later try to delete that pointer, but you can't delete local variables, only variables allocated with new. What you actually want to do is copy the value of i into the dynamically allocated variable.
I think the problem is that by the time you delete each classroom it no longer points to the original memory location of the int created by new because you are not pushing the value of i into the memory location of classroom[i], you are actually changing classroom[i] to point to i's memory location.
Try changing
classroom[i] = &i;
to
*(classroom[i]) = i;
In this loop
for (int i = 0; i < 5; i++) {
classroom[i] = &i;
cout<<*classroom[i]<<endl;
}
You are trashing the memory of the array. You set all of the pointers to the address of i and then when the for loop ends i is destroyed and you now have dangling pointers. attempting to delete them is undefined behavior.
I'm working on a homework and all test on the output are working fine. But I am always getting this Valgrind error:
==22990== Memcheck, a memory error detector
==22990== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==22990== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==22990== Command: ./a.out
==22990== Parent PID: 22989
==22990==
==22990== Invalid read of size 8
==22990== **at 0x401DFB: IntList::removeAll() (IntList.cpp:113**)
==22990== by 0x40113F: main (main.cpp:120)
==22990== Address 0x4c50248 is 8 bytes inside a block of size 16 free'd
==22990== at 0x4A05FD6: operator delete(void*) (vg_replace_malloc.c:480)
==22990== **by 0x401DF6: IntList::removeAll() (IntList.cpp:117)**
==22990== by 0x40113F: main (main.cpp:120)
==22990==
==22990==
==22990== HEAP SUMMARY:
==22990== in use at exit: 0 bytes in 0 blocks
==22990== total heap usage: 2,009 allocs, 2,009 frees, 40,128 bytes allocated
==22990==
==22990== All heap blocks were freed -- no leaks are possible
==22990==
==22990== For counts of detected and suppressed errors, rerun with: -v
==22990== ERROR SUMMARY: 6 errors from 1 contexts (suppressed: 6 from 6)
So it's telling me the that my removeall() function is leaking memory right? The error message talks of line 113 and 117. 113 is the line where while loop starts and 117 is delete temp.
removeall() function:
void IntList::removeAll()
{
NodePtr temp;
temp = head;
if(head == NULL){
cout << "The list is empty" << endl;
return;
}
while (temp-> link != NULL)
{
temp = head;
head = temp->link;
delete temp;
}
}
Can somoene help me out with this? Am I understanding the valgrind error correctly? How can I fix the memory leak?
Sorry if this has been asked before. I tried the search function with no luck.
It's easy to see that you're dereferencing temp in the loop condition after you deleted it at the end of the previous iteration. You're also stopping before you delete the last element. You want something more like
while (NodePtr temp = head) {
head = temp->link;
delete temp;
}
This also behaves correctly if the list is empty, so there's no need to check that beforehand unless you particularly want to print something in that case.
If temp->link is NULL, you never delete temp, thus always having at least one node left in your list.
I think you're missing a delete head; at the end of the function.