I have invalid read of size in the following functions using valgrind. I'm not exactly sure why but if any of you can help me that would be greatly appreciated! From what I can tell it runs okay but there are still some errors that I'm not catching that may even deal with memory allocation and deallocation. Please help!
//alternate constructor that allows for setting of the inital value of the string
MyString::MyString(const char *message)
{
int counter(0);
while(message[counter] != '\0')
{
counter++;
}
Size = counter;
**String = new char [Size];**
for(int i=0; i < Size; i++)
String[i] = message[i];
}
istream& operator>>(istream& input, MyString& rhs)
{
char* t;
int size(256);
t = new char[size];
input.getline(t,size);
**rhs = MyString(t);**
delete [] t;
return input;
}
/*Assignment operator (=) which will copy the source string into the destination string. Note that size of the destination needs to be adjusted to be the same as the source.
*/
MyString& MyString::operator=(const MyString& rhs)
{
if(this != &rhs)
{
delete [] String;
**String = new char[rhs.Size+1];**
Size = rhs.Size;
for(int i = 0; i < Size; i++)
{
** String[i] = rhs.String[i];**
}
}
return *this;
}
Any suggestions?? (All of the problem lines have **)
One thing I see is that your copy constructor doesn't allocate space for \0 and doesn't copy it. Neither does the assignment operator.. Or, if you don't store terminating zero, then why are you looking for it?
and the two implementations differ, why the inconsistency (Size vs counter)?
"From what I can tell it runs okay" - it's called undefined behaviour, or in this case: luck - or, if you like me, and like to catch bugs: a misfortune.
Related
At the moment I have the following member variable in a class:
BYTE *m_pbyImportColumnMappings;
In one of the classes we attempt to read existing data from the registry, and if it is not present, we allocate it. So far, I have changed it like this:
void CImportOCLMAssignmentHistoryDlg::ReadSettings()
{
UINT uSize;
m_dwImportFlags = theApp.GetNumberSetting(theApp.GetActiveScheduleSection(_T("Options")),
_T("ImportFlags"), ImportAssignment::None);
theApp.GetProfileBinary(theApp.GetActiveScheduleSection(_T("Options")),
_T("ImportColumnMappings"), (LPBYTE*)&m_pbyImportColumnMappings, &uSize);
// Reset memory buffer (if required)
if (uSize != (sizeof(BYTE) * 15))
{
if (uSize > 0)
{
delete[] m_pbyImportColumnMappings;
m_pbyImportColumnMappings = nullptr;
}
m_pbyImportColumnMappings = new BYTE[15];
// Default values
const gsl::span column_mappings(m_pbyImportColumnMappings, 15);
std::fill(begin(column_mappings), end(column_mappings), -1);
/*
m_pbyImportColumnMappings[0] = -1;
m_pbyImportColumnMappings[1] = -1;
m_pbyImportColumnMappings[2] = -1;
m_pbyImportColumnMappings[3] = -1;
m_pbyImportColumnMappings[4] = -1;
m_pbyImportColumnMappings[5] = -1;
m_pbyImportColumnMappings[6] = -1;
m_pbyImportColumnMappings[7] = -1;
m_pbyImportColumnMappings[8] = -1;
m_pbyImportColumnMappings[9] = -1;
m_pbyImportColumnMappings[10] = -1;
m_pbyImportColumnMappings[11] = -1;
m_pbyImportColumnMappings[12] = -1;
m_pbyImportColumnMappings[13] = -1;
m_pbyImportColumnMappings[14] = -1;
*/
}
}
My initial change was to use a gsl::span to suppress several warnings about using pointer arithemetic. But I don't know how to turn m_pbyImportColumnMappings into a smart pointer, given the fact that we are attempting to initially populate it from GetProfileBinary.
If I could turn it into a smart pointer then I would not need to deallocate the memory when the class goes out of scope.
In a related answer this code was suggested:
theApp.GetProfileBinary(strSection, strEntry,
reinterpret_cast<LPBYTE*>(&pALI), &uBytesRead);
std::unique_ptr<BYTE[]> cleanup(reinterpret_cast<BYTE*>(pALI));
But, I am not sure how to apply that cleanup method given teh fact we are dealing with a member variable of the class as opposed to an isolated variable in a function.
For a cleaner code, consider using std::vector and a temporary buffer
std::vector<BYTE> m_mapping;
m_mapping.resize(15, -1);
...
UINT len = 0;
BYTE* temp = nullptr;
AfxGetApp()->GetProfileBinary(_T("setting"), _T("key"), &temp, &len);
std::unique_ptr<BYTE[]> cleanup(temp);
if (len == m_mapping.size() * sizeof(m_mapping[0]))
memcpy(m_mapping.data(), temp, len);
else
std::fill(m_mapping.begin(), m_mapping.end(), -1);
std::vector also has automatic cleanup and additional methods.
Otherwise, using std::unique_ptr to replace new/delete for this member data, can be a bit of a nightmare. Example:
m_mapping = nullptr;
GetProfileBinary("setting", "key", &m_mapping, &uSize);
if (uSize != (sizeof(BYTE) * 15))
{
{ std::unique_ptr<BYTE[]> cleanup(m_mapping); }
//delete memory immediately after exiting scope
//note the extra brackets
//allocate new memory and don't manage it anymore
m_mapping = std::make_unique<BYTE[]>(15).release();
if(m_mapping)
for (int i = 0; i < 15; i++) m_mapping[i] = -1;
}
Here we are not able to take advantage of std::unique_ptr memory management, it's only used to turn off warnings.
You don't need any casting here because it just happens that m_pbyImportColumnMappings is BYTE, and GetProfileBinary expects BYTE, it allocates memory using new BYTE
I am trying to populate a number of linked lists on the device and then return those lists back to the hosts.
From my understanding I need to allocate memory for my struct Element, but I don't know how to go about it since I will have many linked lists, each with an unknown number of elements. I've tried a couple of different things but it still didn't work. So I'm back to the starting point. Here is my code:
//NODE CLASS
class Node{
public:
int x,y;
Node *parent;
__device__ __host__ Node(){}
__device__ __host__ Node(int cX, int cY){x = cX; y = cY;}
__device__ __host__ int get_row() { return x; }
__device__ __host__ int get_col() { return y; }
};
//LINKED LIST
class LinkedList{
public:
__device__ __host__ struct Element{
Node n1;
Element *next;
};
__device__ __host__ LinkedList(){
head = NULL;
}
__device__ __host__ void addNode(Node n){
Element *el = new Element();
el->n1 = n;
el->next = head;
head = el;
}
__device__ __host__ Node popFirstNode(){
Element *cur = head;
Node n;
if(cur != NULL){
n = cur -> n1;
head = head -> next;
}
delete cur;
return n;
}
__device__ __host__ bool isEmpty(){
Element *cur = head;
if(cur == NULL){
return true;
}
return false;
}
Element *head;
};
//LISTS
__global__ void listsKernel(LinkedList* d_Results, int numLists){
int idx = blockIdx.x * blockDim.x + threadIdx.x;
Node n(1,1);
if(idx < numLists){
d_Results[idx].addNode(n);
d_Results[idx].addNode(n);
d_Results[idx].addNode(n);
d_Results[idx].addNode(n);
}
}
int main(){
int numLists = 10;
size_t size = numLists * sizeof(LinkedList);
LinkedList curList;
LinkedList* h_Results = (LinkedList*)malloc(size);
LinkedList* d_Results;
cudaMalloc((void**)&d_Results, size);
listsKernel<<<256,256>>>(d_Results, numLists);
cudaMemcpy(h_Results, d_Results, sizeof(LinkedList)*numLists, cudaMemcpyDeviceToHost);
for(int i = 0; i < numLists; i++){
curList = h_Results[i];
while(curList.isEmpty() == false){
Node n = curList.popFirstNode();
std::cout << "x: " << n.get_row() << " y: " << n.get_col();
}
}
}
As you can see I'm trying to populate 10 linked lists on the device and then return them back to the host, but the code above results in unhandled exception - Access violation reading location. I am assuming it is not coping the pointers from the device.
Any help would be great.
Just eyeballing the code, it seems you have a fundamental misconception: there is host memory which cannot be accessed from the device, and device memory which cannot be accessed from the host. So when you create linked list nodes in device memory and copy the pointers back to the host, the host cannot dereference those pointers, because they are pointing to device memory.
If you truly want to pass linked lists back and forth between host and device, your best bet is probably to copy the entries into an array, do the memcpy, then copy the array back into a linked list. Other things can be done too, depending on just what your use case is.
(it is possible to allocate a region of memory that is accessible both from the host and from the device, but there is some awkwardness with it and I have no experience using it)
I have a question concerning working with classes in c++. I must say I'm a beginner. For example, i have this class:
class student {
private:
char* name;
public:
int nrcrt;
student() {
name = new char[7];
name = "Anonim";
nrcrt = 0;
}
student(char* n, int n) {
this->name = new char[7];
strcpy(name, n);
nrcrt = nr;
}
~student() {
delete [] name;
}
char* get_name() {
return this->name;
}
}
void main() {
student group[3];
group[0] = student("Ana", 1);
group[1] = student("Alex", 2);
group[2] = student("Liam", 5);
for (i=0; i<3; i++) {
if (group.nrcrt[i] != 0)
cout << group[i].get_name() << Endl;
}
}
My question is why is it displaying different characters?
first of all your code is not working.
3.cpp:40:18: error: request for member ‘nrcrt’ in ‘group’, which is of non-class type ‘student [3]’
if(group.nrcrt[i]!=0)
i is also not declared.please make proper changes.
group.nrcrt[i]
should be changed to:
group[i].nrcrt
When the array is created, your default constructor is used.
When you assign to the elements, your destructor is called, deleting name.
The default constructor is assigning a literal to name, and deleting that memory has undefined behaviour.
In your default constructor, replace
name = "Anonim";
with
strcpy(name, "Anonim");
Your compiler should have warned you about the assignment.
If it didn't, increase the warning level of your compiler.
If it did, start listening to your compiler's warnings.
do not worry. C++ could look a bit scary as first but it is ok when you get into it. First, let's say that all classes it is good to start with upper case letters. Secondly, you have two constructors (default without parameters and one or more with, in our case one). Default consructor you need to declare an array of objects:
Student group[3];
The next important thing is that you then do not need the rest of the constructors in that case.
group[0]=student("Ana",1);
group[1]=student("Alex",2);
group[2]=student("Liam",5);
Remember to include ; at the end of class declaration. To put all the statements and expression throughout your interation within the same loop. Here is what I found as an errors anf fix them. Could probably have more.
class Student
{
private:
char* name;
public:
int nrcrt;
Student()
{
name=new char[7];
strcpy(name, "Anonim");
nrcrt=0;
}
Student( char* n, int n)
{
this->name=new char[7];
strcpy(name, n);
nrcrt=nr;
}
~Student()
{
delete [] name;
}
char* get_name()
{
return this->name;
}
};
int main()
{
Student group[3];
for(int i=0;i<3;i++)
{
if(group.nrcrt[i]!=0)
cout<<group[i].get_name()<<endl;
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<malloc.h>
int main()
{
char *name;
int a;
name=(char *)malloc(sizeof(name));
printf("no. of names:");
scanf("%d",&a);
int i;
for(i=0;i<a;i++)
{
printf("enter the names:");
scanf("%s",name);
}
for(i=0;i<a;i++)
{
printf("entered names are:%s\n",name);
}
return 0;
free(name);
}
how to print n numbers of entered string in c am already asked this question but i dont got any proper answer any body known the answer please edit my code please if you run my code its displays last string only i dont know why please help..
You need an array of names. To achieve what you are trying to do you can use either a static array with the maximum size or allocate the memory dinamically as in the following program.
Note that you should also test the return value of malloc... just in case.
#include<stdio.h>
#include<string.h>
#include<malloc.h>
int main()
{
char **name;
int a;
printf("no. of names:");
scanf("%d",&a);
int i;
if( a<=0 )
return 0;
name = (char**)malloc( sizeof(char*)*a);
for(i=0;i<a;i++)
{
printf("enter the name:");
name[i]=(char*)malloc( sizeof(char)*128);
scanf("%s",name[i]);
}
for(i=0;i<a;i++)
{
printf("entered names are:%s\n",name[i]);
free(name[i]);
}
free(name);
return(0);
}
Note I had to cast malloc because the compiler that the OP is using raise the error " cannot convert from 'void ' to 'char ** ' " (which means that it's old enough..)
In
name=(char *)malloc(sizeof(name));
name is a char*, so sizeof(name) is the size of an address. Hence you are not allocating enough memory.
Just allocate more memory:
name=(char *)malloc(sizeof(char)*20); //allocating 20 bytes for the block that name will point tor
In addition to wrong space allocation (answered by brokenfoot), you will not get the results you want because you are reading all the names over and over in the same variable name, and later printing the name input last a times:
for(i=0;i<a;i++)
{
printf("enter the names:");
scanf("%s",name);
}
for(i=0;i<a;i++)
{
printf("entered names are:%s\n",name);
}
The right approach would be to use an array to store all the names, and later print them one by one. For example:
for(i=0;i<a;i++)
{
printf("Enter the names:")
scanf("%s",name[a]);
}
print("The entered names are: ");
for(i=0;i<a;i++)
{
printf("%s", name[a]);
}
I want to write myself a function similar to PHP's str_repeat. I want this function to add specified amount of characters at the end of string.
This is a code that does not work (string argument 2 expected!)
void chrrepeat(const char &ch, string &target, const int &count) {
for(int i=0; i<count; i++)
strcat(target, ch);
}
I don't exactly know what language is that (C++?), but you seem to be passing a char to strcat() instead of a null-terminated string. It's a subtle difference, but strcat will happily access further invalid memory positions until a null byte is found.
Instead of using strcat, which is inefficient because it must always search up to the end of the string, you can make a custom function just for this.
Here's my implementation in C:
void chrrepeat(const char ch, char *target, int repeat) {
if (repeat == 0) {
*target = '\0';
return;
}
for (; *target; target++);
while (repeat--)
*target++ = ch;
*target = '\0';
}
I made it return an empty string for the case that repeat == 0 because that's how it works in PHP, according to the online manual.
This code assumes that the target string holds enough space for the repetition to take place. The function's signature should be pretty self explanatory, but here's some sample code that uses it:
int main(void) {
char test[32] = "Hello, world";
chrrepeat('!', test, 7);
printf("%s\n", test);
return 0;
}
This prints:
Hello, world!!!!!!!
Convert char to string.
void chrrepeat(char ch, string &target, const int count) {
string help = "x"; // x will be replaced
help[0] = ch;
for(int i=0; i<count; i++)
strcat(target, help);
}