NSMutableArray goes SIGABRT in multithreaded app... but I _am_ doing #synchronized! - multithreading

Sorry... shame - I didn't run debug mode so the error showed up on the wrong line. In debug-mode, and showing the right line, the error was a simple "dont access an array outside its bounds"-error (typo - i referred to one array but access was to another)
Why does accessing the count of an NSMutableArray produce SIGABRT when I empty the NSMutableArray from another thread? I thought the #synchronized was supposed to do as it's name implies?
NSMutableArray *sourceImageRepArray;
...
#synchronized(self)
{
NSLog(#"singleton 1 %p", self);
unsigned long count = sourceImageRepArray.count; //SIGABRT here!
...
Don't know how much extra code you want me to share... this is the code that triggers it:
#synchronized([Singleton sharedSingleton])
{
NSLog(#"singleton 2 %p", [Singleton sharedSingleton]);
int i, n;
n = [filenames count];
for(i=0; i<n; i++){
ImageRep *item = [[ImageRep alloc] init];
[item setPath:[filenames objectAtIndex:i]];
[[Singleton sharedSingleton].targetImageRepArray insertObject:item atIndex: [targetImageBrowser indexAtLocationOfDroppedItem]];
[item release];
[[Singleton sharedSingleton] removeImageRepFromArray:[Singleton sharedSingleton].sourceImageRepArray withPath:[filenames objectAtIndex:i]];
}
}
singleton 1 == singleton 2:
2011-02-08 07:22:03.265 Crash[60001:5d03] singleton 1 0x200047680
2011-02-08 07:22:03.433 Crash[60001:a0f] singleton 2 0x200047680
why is it not synchronizing?! What else could be going on?

are you sure your self and [Singleton sharedSingleton] are the same object?

Sorry... shame - I didn't run debug mode so the error showed up on the wrong line. In debug-mode, and showing the right line, the error was a simple "dont access an array outside its bounds"-error (typo - i referred to one array but access was to another)
So the solution to my problem was:
Don't do NSLog-debugging in release, it may mark errors on the wrong lines. (sometimes, in multithreaded apps, I guess?)

Related

What's the Easiest Way to Skip a Line in a Managed String^ VC++

I'm trying to Skip a line in a Visual C++ managed String^ or String^ array but I haven't found any easy way to do so. In-fact, I've spent two days on something that would take less than 30 seconds in C#. There is a method .Skip() within C# Enumerable
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.skip?view=netframework-4.7.2
and I'd like something similar for VC++ if possible.
Here's what I've tried:
auto a = gcnew cli::array<String ^>{ "Alpha", "Bravo", "Charlie", "Delta" };
auto xs = gcnew System::Collections::Generic::List<String^>(a);
System::Collections::Generic::IEnumerator<String^>^ e = xs->GetEnumerator();
e->MoveNext();
^^ that throws exception class System::EventArgs has no member "MoveNext"
EDIT: I know what's causing the exception System::EventArgs has no member "MoveNext" .. using ' e ' in Visual Studio causes the compiler to think I'm referring to the e for EventArgs as in e) click_method .. I switched to another name and it populates as this: System.Collections.Generic.List`1+Enumerator[System.String]
I also tried referencing System::Linq and then
System::Collections::Generic::List<String ^>^ _list = gcnew System::Collections::Generic::List<String ^>(System::IO::File::ReadAllLines(filename));
System::Collections::Generic::List<String ^>^ _list2 = _list->Skip(1);
which seems like it would work in C# but get the following exception
class System::Collections::Generic::List has no member skip
so the .NET library doesn't work in CLI / C++
Another thing I attempted was:
System::Collections::Generic::List<String ^>^ _list = gcnew System::Collections::Generic::List<String ^>(System::IO::File::ReadAllLines(filename));
System::Collections::Generic::List<String ^>^ _list2 = _list->RemoveAt(0);
but got exception:
a value of type "void" cannot be used to initialize an entity of type System::Collections::Generic::List^
I'm trying to do it without using marshal_string if possible, but I'm open for any suggestions, as I've been pulling my hair out on this, not sure what else to try =[
EDIT: this reads as an array not a String^ but I couldn't figure out how to do it with a String^ on it's own.
definitely not the quickest way but this skips x number of lines.
I am sick of CLI/C++/VC++ and can't wait to stop using it (I should have never used it in the first place and kick myself daily for not making this in C#).
//read the file to a CLI array (each line is a member)
auto a = System::IO::File::ReadAllLines("test66.txt");
//create a List from the array
auto xs = gcnew System::Collections::Generic::List<String^>(a);
//create a collection from the List
System::Collections::Generic::IEnumerator<String^>^ test66 = xs->GetEnumerator();
//the number of lines we want to skip
int x = 0;
//for loop stopping # x
for (int nxt; nxt <= x; nxt++)
{
test66->MoveNext();
}
//present selected array item to user or you could feed this into a String^
textBox11->Text = test66->Current;
feel free to give a better answer. I couldn't find much information since CLI/C++ is absolutely awful compared to C# and just about every other modern language. (IMO)

how to handle read access violation?

sorry for avoiding you guys
i have a problem with reverse function in circular linked list.
void reverse() {
int num = many;
node* current = head;
node* previous = 0;
while (num != 0) {
cout << "1" << '\t';
node* r = previous;
previous = current;
current = current->next;
previous->next = r;
num--;
}
head = previous;
}
in this func after 2 while sentence
problem comes up in line that current = current->next;
(exception throw : read access violation,
current was 0xDDDDDDDD)
how to handle it??
This is from Visual Studio trying to help you (and succeeding, IMO).
As Mark Ingraham pointed out in another answer a long time ago, Visual Studio's runtime library will fill a block of data with 0xDDDDDDDD when you release a block of heap memory.
So, although you haven't shown any code that's deleting from your list, if there is such code, that's probably the first place to look--at least at first glance, it looks like there's a fair chance that when you try erase a node from the list, you're deleting the memory the node lives in, but still leaving a pointer to that deleted memory.
It's also possible (but less likely, IMO) that you're just using memory without initializing it--and you happen to be hitting a block of memory that was previously allocated and then released back to the heap manager.
The bottom line, however, is that you don't "handle" the access violation. Instead, you need to find the bug in your code that's leading to the access violation happening, and fix it so that doesn't happen any more.

Filling QGraphicsScene with items in thread

I have the thread where the worker object is running infinite cycle. Here I have the following code that I would like it to read coordinates from list and place QGraphicsEllipseItem on these coordinates. The list can be updated by another thread, so I protect it by mutex. But sometimes the size of list may grow up so I would like to create new QGraphicsEllipse items for it if needed.
int meter_to_pixel_ratio = 20;
int x_pixel, y_pixel;
int i;
forever {
visualizationDataMutex->lock();
while(ellipseList->count()<visualizationData->count())
{
qDebug() << "Creating new visual item...";
ellipseList->append(new QGraphicsEllipseItem(0.0, 0.0, 10.0, 10.0));
ellipseList->last()->setVisible(false);
visualizationScene->addItem(ellipseList->last());
}
for(i=0; i<visualizationData->count(); i++)
{
x_pixel = meter_to_pixel_ratio*visualizationData->at(i)->x();
y_pixel = meter_to_pixel_ratio*visualizationData->at(i)->y();
ellipseList->at(i)->setPos(x_pixel, y_pixel);
ellipseList->at(i)->setBrush(QBrush(*visualizationColor->at(i)));
if(!ellipseList->at(i)->isVisible()) ellipseList->at(i)->setVisible(true);
}
visualizationDataMutex->unlock();
// repaint scene
visualizationScene->update();
QThread::msleep(100);
}
The problem I have is, that when I try to run the program I´ll obtain a runtime error. Tried to qDebug() the ellipseList->count() and seems to have the exactly same number of elements as needed (as visualizationData->count()). When commented these three lines:
//ellipseList->at(i)->setPos(x_pixel, y_pixel);
//ellipseList->at(i)->setBrush(QBrush(*visualizationColor->at(i)));
//if(!ellipseList->at(i)->isVisible()) ellipseList->at(i)->setVisible(true);
program can run without crashing. I do not understand why is this happening since there is no other function working with QGraphicsView/QGraphicsScene. (QGraphicsView was added from Qt Designer environment into mainwindow).

Monotouch: Remove all subviews from a view

I am trying to remove all the subviews from a UIView. I tried the following to no effect:
for (int i = 0; i < this.Subviews.Length; i++)
{
this.Subviews[i].RemoveFromSuperview ();
}
Just tested this and it worked for me. (Although your code also looks good to me...)
foreach (UIView view in tableView.Subviews) {
view.RemoveFromSuperview();
}
If it doesn't work for you, there might be something that prevents the subviews from being removed.
The problem with your sample is how you built the loop.
When you remove the view at 0, the Subviews array is one element shorter, and element 1 becomes element 0 on the next iteration. Your i variable on the other hand keeps growing, so you end up skipping view 1.
Try forcing a refresh of the view afterward, or invoking the Remove call specifically on the main thread.
If you absolutely need to use an for loop, this will do
for (int i = this.Subviews.Length - 1 ; i > 0 i--)
{
this.Subviews[i].RemoveFromSuperview ();
}

MemoryLeaking from array with dictionaries

I have my function getAllData, which is returning an array with dictionaries.
- (NSArray *)getAllData {
NSMutableArray *result = [[NSMutableArray alloc] init];
NSArray *data = [skiResorts sortedArrayUsingFunction:comparator context:NULL];
NSString *currentLetter = #"A";
NSMutableArray *array = [[NSMutableArray alloc] init] ;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init] ;
if ([data count] > 0) {
for (SkiResort *resort in data) {
if ([resort.name hasPrefix:currentLetter]) {
// Same letter as before.
// Add current SkiResort to temporary array.
[array addObject:resort];
} else {
// New letter.
// Add previous header/row data to dictionary.
[dict setValue:currentLetter forKey:#"header"];
[dict setValue:array forKey:#"row"];
// Add dictionary to final result array.
[result addObject:dict];
// Startover ...
[array removeAllObjects];
[dict removeAllObjects];
// Prepare for next letter.
currentLetter = [resort.name substringToIndex:1];
// Add current SkiResort to temporary array.
[array addObject:resort];
}
}
// Add previous header/row data to dictionary.
[dict setValue:currentLetter forKey:#"header"];
[dict setValue:array forKey:#"row"];
// Add dictionary to final result array.
[result addObject:dict];
}
[array release];
[dict release];
return [result autorelease];
}
Can anyone see obvious memory leaks in my code? I get memory leak array, dict, and result...
From the code, I have to ask: you're aware that addObject: doesn't copy the object? So setting values to dict, then adding it to result, then removing everything from dict just leaves an empty dictionary in result? I think you probably want to use the 'copy' method in there, to make copies of the array and dictionary. Or, even better, just create the dictionary when you add it to result using one of the class methods.
Anyway, since I can't see any leaks in that, much more likely is that whoever receives the result of getAllData subsequently leaks it. If for some crazy reason you had somewhere a stray:
[[object getAllData] retain];
Then the leaks tool would identify a leak of array, dict and result and point you to getAllData as the method in which they were originally created.
I really should say before I answer my knowledge on this is VERY limited, so take that into consideration. But it seems to me like you have a container inside a container. And when u reserve memory for that you have to backwards unreserve it.
For example, Store n (B_Containers) in Container A reserves n_B containers and 1 A container. To unreserve the memory you need to unreserve n B_Containers first before you delete A or all B_Containers will be withou reference and floating around in your memory.

Resources