NSValue: getValue: странное поведение, почему это происходит? - PullRequest
3 голосов
/ 12 августа 2011

Я пытаюсь передать CGRect в NSInvocation (setArgument: atIndex :).Я обертываю его NSValue, нажимаю NSArry, затем получаю из NSArray и использую NSValue (getValue :).Вызов метода (getValue :) вызывает изменение ранее объявленного индекса NSInteger i.Кто-нибудь может сказать, почему это происходит?

 NSString className = @"UIButton";
    Class cls = NSClassFromString(className);
    cls pushButton5 = [[cls alloc] init];
    CGRect rect =CGRectMake(20,220,280,30);
    NSMethodSignature *msignature1;
    NSInvocation *anInvocation1;

    msignature1 = [pushButton5 methodSignatureForSelector:@selector(setFrame:)];
    anInvocation1 = [NSInvocation invocationWithMethodSignature:msignature1];

[anInvocation1 setTarget:pushButton5];
[anInvocation1 setSelector:@selector(setFrame:)];
NSValue* rectValue = [NSValue valueWithCGRect:rect];
NSArray *params1;
params1= [NSArray arrayWithObjects:rectValue,nil];
id currentVal = [params1 objectAtIndex:0];
NSInteger i=2;
if ([currentVal isKindOfClass:[NSValue class]]) {
    void *bufferForValue;
    [currentVal getValue:&bufferForValue];
    [anInvocation1 setArgument:&bufferForValue atIndex:i];
}else {
    [anInvocation1 setArgument:&currentVal atIndex:i];
}
[anInvocation1 invoke];

Когда этот метод (getValue:) реализует изменение значения 'i' с 2 на что-то вроде: 1130102784, а в (setArgument:atIndex:) у меня есть SIGABRT, потому что индекс iвыходит за пределы.

Так почему [NSValue getValue:(*void) buffer] меняет другие переменные?

(PS Я делаю это в функции, поэтому я упростил пример и инициализировал массив напрямую. И если я установил непосредственно atIndex: 2, он работает отлично. Но, как мне грустно, я немного упростила, и мне нужно передать i в atIndex:)


Благодаря Тому Даллингу (особенно) и проблема Серхио решена.Я удаляю это:

void *bufferForValue;
[currentVal getValue:&bufferForValue];
[anInvocation1 setArgument:&bufferForValue atIndex:i];

и вставляю это

NSUInteger bufferSize = 0;
NSGetSizeAndAlignment([currentVal objCType], &bufferSize, NULL);
void* buffer = malloc(bufferSize);
[currentVal getValue:buffer];
[anInvocation1 setArgument:buffer atIndex:i];

Спасибо.Stackoverflow.com действительно полезный сайт с умными людьми.

Ответы [ 2 ]

8 голосов
/ 12 августа 2011

Вы не можете вписать NSRect в void*.Правильный код будет:

NSRect buffer;
[currentVal getValue:&buffer];

Или, если вы не знаете содержимое объекта NSValue:

NSUInteger bufferSize = 0;
NSGetSizeAndAlignment([currentVal objCType], &bufferSize, NULL);
void* buffer = malloc(bufferSize);
[currentVal getValue:buffer]; //notice the lack of '&'
//do something here
free(buffer);

Значение для i меняетсяпотому что ваш код вызывает переполнение других переменных, выделенных стеком.

2 голосов
/ 12 августа 2011

In:

 void *bufferForValue;
 [currentVal getValue:&bufferForValue];

вы копируете значение currentVal в буфер размером void* (указатель);см. getValue ссылка :

getValue:

Копирует значение получателя в заданный буфер.

Буфер для копирования значения получателя.буфер должен быть достаточно большим, чтобы содержать значение.

Поскольку значение, которое вы копируете в буфер, не помещается в void*, вы перезаписываете свой стек, так как записываете по адресулокальной переменной;это, вероятно, приводит к перезаписи локальной переменной i, что объясняет, что происходит.

...