I have a passed in unmanaged buffer with a type like this BYTE*, so this is a byte buffer and length information is also known, and now I want to use byte buffer to create a vector like this std::vector<BYTE>,
I know I could use copy and manually delete this buffer later like following,
foo(BYTE* in, int size) {
...
std::vector<BYTE> vec;
std::copy(in, in + size, std::back_inserter(vec));
...
}
My question is what is the best way to avoid a copy here? I feel there should be a good way to create this vector so that this vector takes ownership of this buffer using given pointer, aside from avoid a copy, another advantage is that I don't have to manually delete this buffer after copy. I think there is definitely some elegant way to do this safely.
Related
I have a NSString which i have to convert into NSData. After converting into NSData, I need to transpose the NSData in objective-c.
How do i transpose NSData in objective -c ?
Thanks
It seems you wish to reverse the order of the bytes, here is an outline algorithm:
Use NSData's length to get the number of bytes
Allocate a C-array of type Byte to hold the bytes. Use one of the malloc() family.
Use getBytes:length: to get a copy of the bytes
Set a C Byte * variable, say frontPtr, to point at the first byte; set another, say rearPtr to point at the last byte.
Now iterate, exchanging the bytes referenced by the two pointers, then increment frontPtr, decrement rearPtr, and keep iterating while rearPtr > frontPtr.
Create a new NSData from the working buffer using NSData's + dataWithBytesNoCopy:length:freeWhenDone: passing YES as the last argument - this will take ownership of the malloc'ed buffer so there is no need for you to free it.
The algorithm simply moves two pointers from the ends of the buffer towards the middle exchanging bytes as it goes. The termination condition make it work for even and odd lengths (in the latter case the middle byte doesn't need to be swapped).
If one the other hand you didn't wish to reverse the order of the bytes, but instead reverse the order of bits in each byte Google "C bit reverse" and follow the same general structure as the above algorithm but do bit reversing in the loop.
If after coding the above you have a problem ask a new question, include your code, and explain your issue. Someone will undoubtedly help you.
HTH
I've got a question about what I think boils down to C syntax and memory considerations. I have a callback in an Objective-C class that processes some audio, and one of the arguments is bufferListInOut. It represents a mono audio signal that I'd like to convert to stereo. Here's my code:
static void tap_ProcessCallback(MTAudioProcessingTapRef tap,
CMItemCount numberFrames,
MTAudioProcessingTapFlags flags,
AudioBufferList *bufferListInOut,
CMItemCount *numberFramesOut,
MTAudioProcessingTapFlags *flagsOut){
// Retrieve mono audio data into bufferListInOut
MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, NULL, NULL, NULL);
// Copy the mono channel's data
float *channelLeft = malloc(numberFrames * sizeof(float));
channelLeft = bufferListInOut->mBuffers[0].mData;
// Attempt to create a second channel which is (currently) a copy of the first
bufferListInOut->mNumberBuffers = 2; // 2 for stereo, 1 for mono
bufferListInOut->mBuffers[1].mNumberChannels = 1;
bufferListInOut->mBuffers[1].mDataByteSize = numberFrames * sizeof(Float32);
bufferListInOut->mBuffers[1].mData = channelLeft;
// Set number of frames out
*numberFramesOut = numberFrames;
}
Some notes:
In this code, the new channel is just a copy of the original, but in practice it will undergo some processing.
The naming is a little weird, but mNumberBuffers is indeed meant to be 2 and mNumberChannels is meant to be 1.
This crashes with an EXC_BAD_ACCESS error on a rendering thread down the line. So, my question is what is the right way to add a new buffer to this struct? I don't delve into C too often, so I'm sure I'm missing some basics here. Any pointers on this would be great. Thanks for reading.
You cannot do what you are attempting, at least in the way you are trying to do it. The type AudioBufferList is declared as:
struct AudioBufferList { UInt32 mNumberBuffers; AudioBuffer mBuffers[1]; };
This is a classic C pattern for a variable sized struct. To create a struct for N buffers a single block of memory is allocated with the size:
sizeof(UInt32) + N * sizeof(AudioBuffer)
The address of that block is assigned to a AudioBufferList * variable and the field mNumberBuffers set to N. You cannot simply increase the mNumberBuffers to increase the size of the array, instead you must either allocate a new complete struct, or realloc the existing one - realloc increases the size of memory block if possible or allocates a new one and copies the existing data into it if not.
Given your tap_ProcessCallback() function is passed a AudioBuuferList * value and does not return one, there is no way it can change the size of the struct (i.e. the number of buffers) it is passed.
As pointed out in comments you are also doing pointer assignment when you intend to copy memory - see memcpy and friends.
So you need a redesign - your goal is possible, just not how and where you've attempted it.
HTH
Out of pure curiosity, I started playing with array's in ways that I have never used before. I tried making a data structure array, and set it equal to another:
typedef struct _test {
float value;
} test;
Simple enough struct, so I tried this:
test struct1[10];
test struct2[20];
struct1 = struct2;
I didn't think this would work, and it didn't even compile. But, this interests me a lot. Is it possible to take an array of 10 and increase the size to 20, while copying the data?
Objective-C
I am actually doing this with Objective-C, so I'd like to hear from the Objective-C people as well. I want to see if it is possible to change the size of struct1 in this file.
#interface Object : NSObject {
test struct1;
}
Remember: This is only out of curiosity, so everything is open to discussion.
Something else that is not exactly pertinent to your question but is interesting nonetheless, is that although arrays cannot be assigned to, structs containing arrays can be assigned to:
struct test
{
float someArray[100];
};
struct test s1 = { /* initialise with some data*/ };
struct test s2 = { /* initialise with some other data */ };
s1 = s2; /* s1's array now contains contents of s2's array */
This also makes it possible to return fixed-length arrays of data from functions (since returning plain arrays is not allowed):
struct test FunctionThatGenerates100Floats(void)
{
struct test result;
for (int i = 0; i < 100; i++)
result.someArray[i] = randomfloat();
return result;
}
As others have said, arrays allocated like that are static, and can not be resized. You have to use pointers (allocating the array with malloc or calloc) to have a resizable array, and then you can use realloc. You must use free to get rid of it (else you'll leak memory). In C99, your array size can be calculated at runtime when its allocated (in C89, its size had to be calculated at compile time), but can't be changed after allocation. In C++, you should use std::vector. I suspect Objective-C has something like C++'s vector.
But if you want to copy data between one array and another in C, use memcpy:
/* void *memcpy(void *dest, const void *src, size_t n)
note that the arrays must not overlap; use memmove if they do */
memcpy(&struct1, &struct2, sizeof(struct1));
That'll only copy the first ten elements, of course, since struct1 is only ten elements long. You could copy the last ten (for example) by changing &struct2 to struct2+10 or &(struct2[10]). In C, of course, not running off the end of the array is your responsibility: memcpy does not check.
You can also you the obvious for loop, but memcpy will often be faster (and should never be slower). This is because the compiler can take advantage of every trick it knows (e.g., it may know how to copy your data 16 bytes at a time, even if each element is only 1 byte wide)
You can't do this in C with static arrays, but you can do it with dynamically allocated arrays. E.g.,
float *struct1, *struct2, *struct3;
if(!(struct1 = malloc(10 * sizeof(float))) {
// there was an error, handle it here
}
if(!(struct2 = realloc(struct1, 20 * sizeof(float))) {
// there was an error, handle it here
// struct1 will still be valid
}
if(!(struct3 = reallocf(struct2, 40 * sizeof(float))) {
// there was an error, handle it here
// struct2 has been free'd
}
In C, I believe that's a good place to use the realloc function. However, it will only work with dynamically allocated arrays. There's no way to change the memory allocated to struct1 by the declaration test struct1[10];.
In C arrays are constants, you can't change their value (that is, their address) at all, and you can't resize them.
Clearly if you declare your array with a fixed size, test struct1[10] then it cannot be resized. What you need to do is to declare it as a pointer:
test *struct1;
Then you must use malloc to allocate the array and can use realloc to resize it whilst preserving the contents of the original array.
struct1 = malloc(10*sizeof(*struct1));
//initialize struct1 ...
test *struct2 = realloc(struct1, 20*sizeof(*struct1));
If you're using Objective C, you know you can just use NSMutableArray, which automatically does the realloc trick to reallocate itself to store however many objects you put in it, up the limit of your memory.
But you're trying to do this with struct? What would that even mean? Suppose you increase the amount of memory available to struct1 in Object. It's still a struct with one member, and doesn't do anything more.
Is the idea to make Object be able to contain an expanded struct?
typedef struct _test2 {
float value;
NSObject *reference;
} test2;
But then you still can't access reference normally, because it's not a known part of Object.
Object *object2;
...
NSLog(#"%#", object2.struct1.reference); // does not compile
If you knew you had one of your modified objects, you could do
Object *object2;
...
NSLog(#"%#", ((test2)(object2.struct1)).reference);
And also you could still presumably pass object2 to anything that expects an Object. It only has any chance of working if struct1 is the last member of Object, and don't mess with subclassing Object either.
Some variety of realloc trick might then work, but I don't think realloc in particular, because that's intended to be used on objects that are allocated with malloc, and the details of what C function is used to allocate objects in not exposed in Objective C, so you shouldn't assume it's malloc. If you override alloc then you might be able to make sure malloc is used.
Also you have to watch out for the fact that it's common in Objective C for more than one pointer to an object to exist. realloc might move an object, which won't be semantically correct unless you correct all the pointers.
We have an NSMutableData object that frequently has data appended to it. We also frequently pull out data via the bytes method for reading.
We've synchronized access to this NSMutableData object via a pthread mutex:
pthread_mutex_t _mutex;
pthread_mutexattr_t attributes;
pthread_mutexattr_settype( &attributes, PTHREAD_MUTEX_DEFAULT );
pthread_mutex_init( &_mutex, &attributes );
and then every time we access this object we:
pthread_mutex_lock(&_mutex);
const UInt8* rawData = [_coverage bytes];
//code that works with the raw bytes
pthread_mutex_unlock(&_mutex);
Also, every addData method we have locks the mutex before adding data to the NSMutableData object.
The problem is we still get the occasional EXC_BAD_ACCESS while working with rawData. I understand that NSMutableBytes will grow its byte array as data gets added to it. I also understand that I shouldn't expect rawData to magically grow also.
I'm just wondering how we can ever get into this situation where rawData has been free'd from underneath us when we have explicitly locked access for both read and write?
Are we doing something wrong with the mutex or the way we are accessing the bytes?
EDIT
I discovered the real reason why I was getting an EXC_BAD_ACCESS. I was not initializing the mutex attributes, so locking the mutex did nothing. Here is the corrected code:
pthread_mutex_t _mutex;
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
pthread_mutex_init(&_mutex, &attributes);
pthread_mutexattr_destroy(&attributes);
Yes it is possible that is being freed from underneath you.
According to the documentation:
bytes
Returns a pointer to the receiver’s contents.
You should make copies of the data to ensure that it will not be changed or freed from underneath you. When your done with your copy make sure to free() it.
pthread_mutex_lock(&_mutex);
const UInt8 *origData = [_coverage bytes];
UInt8 *rawData;
memmove(rawData, origData, [_coverage length]);
//code that works with the raw bytes
free(rawData);
pthread_mutex_unlock(&_mutex);
I've been programming for a while in objective-c, but I've unfortunately never delved very deeply into C and memory pointers, although I do have a rudimentary understanding of them. I'm working with an array of CLLocationCoordinate2D structures, and I'm trying to figure out how to append to the array. First of all, I get the
NSString *aString; //a bunch of coordinates
CLLocationCoordinate2d *coordinates;
int length;
doSomethingCool(aString, &coordinates, &length);
after I do something cool, I want to preserve it in a class variable. If I simply do something like
points = newPoints
points contains the appropriate contents. However, if I try to do something like this:
points = malloc(sizeof(CLLocationCoordinate2D) * length);
points[0] = *newPoints;
points ends up with contents different from newPoints.
Ultimately my goal is to be able to append to points based on length, but I'm not going to be able to do that if I can't get the above code to work. What am I doing wrong?
Your code simply copies the first value of newPoints into the first value of points (*newPoints is equivalent to newPoints[0]).
One situation is to make a new array, copy all values, switch the arrays, and free() the old one. For example:
int* newvals = malloc(sizeof(int) * newcount);
memcpy(newvals, vals, sizeof(int) * oldcount);
free(vals);
vals = newvals;
You can also use realloc - its behavior is similar to the above (though it can fail!), but at times may be more efficient.
Note that you simply can't change the underlying pointer's size in a safe and portable fashion. You will need to update your instance ("class") variable with the new pointer.
The idea would be to copy all of the array into a temporary array, resize the original, and then copy them back. However, managing this could get hairy. You'd be better off using an std::vector and just appending it.
EDIT: I just realized you're using C, not C++. Disregard the second half of this.