I have some C++ function like below:
void fillBuffer(char* buffer, int len) {
for (int i = 0; i < len; i++) {
buffer[i] = 1;
}
}
void fillByPointerOfBuffer(char **pBuffer, int len) {
fillBuffer(*pBuffer, len);
}
void printBuffer(char* buffer, int len) {
for (int i = 0; i < len; i++) {
printf("%d", buffer[i]);
}
}
In my main program, I try some test as below:
Test 1:
char *buffer = new char[6];
fillByPointerOfBuffer(&buffer, 6);
printBuffer(buffer, 6);
delete[] buffer;
// --> It output: 111111
Test 2:
char buffer[6];
fillByPointerOfBuffer( (char**)(&buffer), 6);
printBuffer(buffer, 6);
// --> Exception thrown: write access violation.
Test 3:
char buffer[6];
char *buffer2 = buffer;
fillByPointerOfBuffer(&buffer2, 6);
printBuffer(buffer, 6);
//// --> It output: 111111
In Test1, pointer to dynamic allocated array is passed to function fillByPointerOfBuffer.
In Test2, pointer to fixed length array is passed to function fillByPointerOfBuffer.
In Test3, pointer to "alias" variable of fixed length array is passed to function fillByPointerOfBuffer.
I think that they all must be the same, but why Test1 and Test3 worked, but Test2 does not work?
Related
I am practicing c++ and this code is supposed to copy an array to another array.output types are character and which is passed by pointer through the function 'f'. my output type is pointer which is pointing to a char array.here is my code:
using namespace std;
void f(char*, char*);
int main()
{
char *a1;
char a2[] = "1234";
f(a1, a2);
cout << a1<< endl;
return 0;
}
void f(char *a, char *b)
{
int len;
len = sizeof(b) / sizeof(b[0]);
a = new char[len];
for (; (*a=*b )!= '\0'; a++, b++)
cout<<*a<<endl;
for (int i=0;i<4;i++)
cout<<a[i]<<endl;
}
in the function each time for loop runs 'a' elements changes to the unreadable value. at first, it shows right value and then it changes. for example, in the first loop inside the function, it prints right value of 'a' but in second loop it changes it for no reason!
this function doesn't return any value. as I expect by calling by pointer it has to change the variable but nothing happens.
deep explanation is appreciated. I am completely new in c++ programming.
Without changing the basic style of your code, here is a fixed version, with comments:
#include <iostream>
using namespace std;
void f(char**, char*); // You need to pass a pointer to the pointer!
void f2(char*&, char*); // Alternative passing the pointer by reference
int main()
{
char* a1;
char a2[] = "1234";
// f(&a1, a2); // Pass the address of the 'a1' pointer
f2(a1, a2); // a1 pointer is now passed by reference
cout << a1 << endl;
delete a1[]; // Here, we free the memory allocated by the new call!
return 0;
}
void f(char** a, char* b)
{
int len;
// len = sizeof(b) / sizeof(b[0]); // You can't get the array length like this!
len = strlen(b); // Assuming your string is null-terminate!
*a = new char[len + 1]; // Make room for the null terminator!
// Make a copy of the pointer (atemp) - otherwise you are changing the address of the new character
// array you just created - and this will then fail in the 2nd loop ...
for (char* atemp = *a; (*atemp = *b) != '\0'; atemp++, b++)
cout << *atemp << endl;
for (int i = 0; i < len; i++) // Length won't always be 4!
// for (int i = 0; i < 4; i++)
cout << (*a)[i] << endl;
}
void f2(char*& a, char* b)
{
size_t len = strlen(b); // Assuming your string is null-terminate!
a = new char[len + 1];
for (char* atemp = a; (*atemp = *b) != '\0'; atemp++, b++)
cout << *atemp << endl;
for (int i = 0; i < len; i++) // Length won't always be 4!
cout << a[i] << endl;
}
Feel free to ask for more details about why the changes were made!
EDIT: Added alternative using argument as a reference.
A lot of mistakes in your program:
void f(char *a, char *b)
{
len = sizeof(b) / sizeof(b[0]);
b is a pointer to char. As this it has the pointer size of the machine type, typically it is 32 or 64 bit. So you never get the size of the array!
If you really want to pass a raw pointer to char to a function and want to handle the data stored at the position where the pointer points to, you have either to pass also the size ( number of elements ) or you have to know an end mark. In case of a c-sytle string you have a '\0' at the end of the string which makes it possible to use it.
So you have first to count the number of elements until '\0' is reached, allocate a new array, copy the elements and than return the pointer.
Next failure: If you allocate memory with new, you have to use delete later in your program.
But:
What you did is bad sytle C code! It has really nothing todo with C++ nor with good C. There is no need to write a own string copy function as there is already strcpy and strlen to get the size.
In C++ your code can be something like that:
void f( const std::string& src, std::string& target )
{
target = src;
}
int main()
{
std::string a2{"abcd"};
std::string a1;
f( a2, a1 );
std::cout << a1 << std::endl;
}
I'm having trouble trying to come up with the pointer version of this function:
void strncpy(char t[], const char s[], const unsigned int n)
{
unsigned int i = 0;
for(i = 0; i < n and s[i]; i++)
t[i]=s[i];
t[i] = '\0'
}
This function is supposed to copy the first "n" characters of one array to another array and then terminate with a null character. I'm sure this is simple but I'm still learning pointers :P
This is what I have right now:
void strncpy(char * t, const char * s, const unsigned int * n)
{
unsigned int i = 0;
for(i = 0; i < *n and *s; i++)
*t = *s;
*t = '\0';
}
Im calling it in main via:
char array_one[5] = "quiz";
char array_two[5] = "test";
unsigned int x = 2;
strncpy(array_one,array_two,x);
You've failed to increment the pointers, so you're always overwriting the same address. There's also no need to pass n via a pointer:
#include <cstddef>
void my_strncpy(char *t, const char *s, std::size_t n) {
while (n && *s) {
*t++ = *s++;
--n;
}
*t = '\0';
}
NB: note use of size_t to duplicate the standard parameter signature
of the standard strncpy function, although the standard version also returns the original value of t rather than void.
#include <iostream>
// changing the function signature to take an int instead of
// pointer to int - cleaner
void my_strncpy(char * t, const char * s, const unsigned int n)
{
unsigned int i = 0;
for(i = 0; i < n; i++)
{
*t++ = *s++; // copy and increment
}
*t = '\0'; // fixing - added terminating char
}
int main(void)
{
char a[] = "string1";
char b[] = "string2";
my_strncpy(a,b,7); // replace 7 with appropriate size
std::cout << a << std::endl;
}
You need to copy over each character from one string to another and then increment the pointers - you were missing that in your implementation.
I also assume that you will not overshoot the array you are copying from.
I try to pass my dynamic array of structs to kernel but it doesn't works. I get - "Segmentation fault (core dumped)"
My code - EDITED
#include <stdio.h>
#include <stdlib.h>
struct Test {
unsigned char *array;
};
__global__ void kernel(Test *dev_test) {
}
int main(void) {
int n = 4;
int size = 5;
unsigned char *array[size];
Test *dev_test;
// allocate for host
Test *test = (Test*)malloc(sizeof(Test)*n);
for(int i = 0; i < n; i++)
test[i].array = (unsigned char*)malloc(size);
// fill data
for(int i=0; i<n; i++) {
unsigned char temp[] = { 'a', 'b', 'c', 'd' , 'e' };
memcpy(test[i].array, temp, size);
}
// allocate for gpu
cudaMalloc((void**)&dev_test, n * sizeof(Test));
for(int i=0; i < n; i++) {
cudaMalloc((void**)&(array[i]), size * sizeof(unsigned char));
cudaMemcpy(&(dev_test[i].array), &(array[i]), sizeof(unsigned char *), cudaMemcpyHostToDevice);
}
kernel<<<1, 1>>>(dev_test);
return 0;
}
How correctly I should allocate gpu memory and copy data to this memory?
You need to allocate memory for struct member array.
Test *test = malloc(sizeof(Test)*n);
for(int i = 0; i < n; i++)
test[i]->array = malloc(size);
I would suggest to read this answer to cope up with other issues after this fix.
what is your card ? if your card support compute capability >= 3.0, try the unified memory system , to have same data in host/device memory
you can have a look here :
it should maybe look like this one :
int main(void) {
int n = 4;
int size = 5;
Test *test;
cudaMallocManaged(&test, n * size);
unsigned char values[] = { 'a', 'b', 'c', 'd' , 'e' };
for(int i=0; i<n; i++)
{
unsigned char* temp;
cudaMallocManaged(&temp, size*sizeof(char) );
memcpy(temp, values, sizeof(values) );
}
// avoid copy code, makes a deep copy of objects
kernel<<<1, 1>>>(test);
return 0;
}
And i hope you know it, but Don't forget do call cudaFree & delete/free on allocated memory. (better to use std::vector and use data() to access to raw pointer)
I would like to write a function (changeSize) that uses DMA, where I can choose to change it's (an array's) size to whatever I want, where oldEls is the original size, and newEls is the new size. If newEls is larger than oldEls, I would just add zero's to the end, and if it is smaller than oldEls, I would just truncate. The "ptr" parameter needs to point to the new array. It is my understanding that this would be similar to the C realloc() function.
With the code presently below, I am outputting the following: 0, 0, 3, 6, 0, 0, 0, 0, where the correct output should be 4, 2, 3, 6, 0, 0, 0, 0. I also realize that my show function is maybe not the best function to output the new array, since I have to explicit state the array element size.
Thanks in advance.
#include <iostream>
#include <cstdlib>
using namespace std;
void show( const int a[], unsigned elements );
int * copy( const int a[], unsigned els );
void changeSize( int * & ptr, int newEls, int oldEls );
void die(const string & msg);
int main()
{
int arr[4] = {4, 2, 3, 6};
show(arr, 4);
int * newArr = copy(arr, 4);
cout << endl << endl;
changeSize(newArr, 8, 4);
show(newArr, 8);
}
void show( const int a[], unsigned elements )
{
for (int i = 0; i < elements; i++)
cout << a[i] << endl;
}
int * copy( const int a[], unsigned els )
{
int *newArr;
try
{
newArr = new int[els];
}
catch(const bad_alloc &)
{
die("Copy: Alloc Failure");
}
for (int i = 0; i < els; i++)
newArr[i] = a[i];
return newArr;
}
void changeSize( int * & ptr, int newEls, int oldEls )
{
int * newArr;
try
{
newArr = new int[newEls];
for (int i = 0; i < oldEls; i++)
{
newArr[i] = ptr[i];
}
if (newEls > oldEls)
{
for (int k = oldEls; k < newEls; k++)
newArr[k] = 0;
}
}
catch(const bad_alloc &)
{
die("changeSize: Alloc Failure");
}
ptr = newArr;
delete[] newArr;
}
void die(const string & msg)
{
cerr << "Fatal error: " << msg << endl;
exit(EXIT_FAILURE);
}
First of, you call delete on newArr at the end of changeSize. you need to delete the old value of ptr (that you currently discard). That's (probably) the problem
While I'm at it, I'd like to point your interest to std::vector. It's basically a resizeable array.
Also, copying raw chucks of memory is still best done with memcpy, don't waste your time with writing for loops just to copy ints, do that only for C++ classes.
EDIT: using std::copy is the best solution for C++, it uses memcpy when it can, otherwise it's the same as a for loop copying the objects.
Cheers!
I am trying to create my own strlen and substr functions and I have 1 problem.
for example, let say I have the string ABC, my strlen will return 3, let say I want to cut this string from 0 to 1 its should return to me A,but I get some trash values, if I insert the substr to a new char and check the length I will recieve 14.
this is my code:
int len(char *w){
int count=0;
int i=0;
while (w[i]!='\0')
{
count++;
i++;
}
//cout<<"Length of word is:"<<count<<"\n";
return count;
}
char *subs(char *w,int s,int e){
int i,j;
int size=0;size=(e-s);
//cout<<"new size is:"<<size<<"\n";
char *newW=new char[size];
for(i=0,j=s;j<e;i++,j++)
{
newW[i]=w[j];
}
return newW;
}
int main(){
char* x="ABC";
//int v=len(x);
//cout<<v;
char *n=subs(x,0,1);
cout << len(n);
for(int g=0;g<len(n);g++)
//cout<<n[g];
return 0;
}
I would like to get some comments what I did wrong, Thanks!
Change your condition loop for for(i = 0, j = s ; j < e && w[j] != '\0'; i++, j++) and you need to allocate size +1 since you have to add a \0 at the end of the string.
sub string should end with a '\0', the array size should add one. Here is the code:
char *subs(char *w,int s,int e){
int i,j;
int size=0;size=(e-s);
//cout<<"new size is:"<<size<<"\n";
char *newW=new char[size + 1];
for(i=0,j=s;j<e;i++,j++)
{
newW[i]=w[j];
}
newW[i] = '\0';
return newW;
}