Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 从块、NSAlert和OS X管理C字符串_Objective C_Macos_Cocoa - Fatal编程技术网

Objective c 从块、NSAlert和OS X管理C字符串

Objective c 从块、NSAlert和OS X管理C字符串,objective-c,macos,cocoa,Objective C,Macos,Cocoa,我已经编写了一段测试代码“AlertTest”,以确保以正确的方式实现了NSAlert对象。它由一个按钮组成,该按钮触发打印C字符串的[doSomething:cstr],以及一个发布警报的方法,该方法将相同的字符串传递给相同的方法,但来自完成处理程序。 这是调试器控制台打印输出: -从[按下按钮] 2015-01-09 18:28:09.832 AlertTest[1260:40881] Application must quit Application must quit 2015-01-

我已经编写了一段测试代码“AlertTest”,以确保以正确的方式实现了NSAlert对象。它由一个按钮组成,该按钮触发打印C字符串的[doSomething:cstr],以及一个发布警报的方法,该方法将相同的字符串传递给相同的方法,但来自完成处理程序。 这是调试器控制台打印输出:

-从[按下按钮]

2015-01-09 18:28:09.832 AlertTest[1260:40881] Application must quit
Application must quit
2015-01-09 18:28:12.276 AlertTest[1260:40881] @Èø_ˇ
@\351\277_\377
-从[mPostError:cstr]

2015-01-09 18:28:09.832 AlertTest[1260:40881] Application must quit
Application must quit
2015-01-09 18:28:12.276 AlertTest[1260:40881] @Èø_ˇ
@\351\277_\377
我对如何从完成处理程序中正确传递字符串有点困惑。没有报告编译器错误。我一定错过了一些很明显的东西。提前谢谢。代码如下:

//___________________________________________________________
- (IBAction)buttonPressed:(NSButton *)sender {
char cstr[256];
strcpy(cstr, "Application must quit");
[self mDoSomething:cstr];
[self mPostError:cstr];
}
//___________________________________________________________
-(void)mDoSomething: (char*)cstr
{
NSLog(@"%s",cstr);
printf("%s\n", cstr);
}
//___________________________________________________________
-(void) mPostError: (char *)cstr
{
char cMessage[64] = "Critical Error";
NSString *message = [NSString stringWithCString:cMessage encoding:NSASCIIStringEncoding];
NSString *infoText = [NSString stringWithCString:cstr encoding:NSASCIIStringEncoding];
NSAlert* mAlert = [[NSAlert alloc] init];
[mAlert setMessageText:message];
[mAlert setInformativeText:infoText];
[mAlert setAlertStyle: NSCriticalAlertStyle];
[mAlert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
 [self mDoSomething: cstr]; //this is the suspect line!
}];
}

您的问题与C字符串无关,而是与变量生存期有关

您的执行流程如下所示:

  • 按钮按下:
    被调用。这将创建一个局部变量
    cstr
    ,并调用
    mPostError:

  • mPostError:
    被调用。这将调用
    beginSheetModalForWindow:completionHandler:
    并向其传递一个块。该块引用了
    cstr
    ,因此复制了
    cstr
    中的值,该值是按下的
    按钮的地址:
    的同名局部变量

  • mPostError:
    返回使我们回到

  • 按钮按下:
    ,然后返回其局部变量
    cstr
    。传递给
    beginSheetModalForWindow:completionHandler:
    的块现在的地址指向已释放的内存

  • 用户解除警报并调用块。该块调用
    mDoSomething:
    将现在无效的地址传递给它

  • mDoSomething:
    调用
    printf
    ,该函数试图将传递地址处的内存解释为C字符串,但到目前为止,该内存已被重新用于其他用途,并产生了您所看到的无意义

  • 传递C字符串不是问题,但传递给块的任何值(本例中为
    char*
    值)在执行块时都必须有效

    您可以通过将
    cstr
    设置为全局变量来“修复”示例中的问题:

    char cstr[256]; // global
    
    - (IBAction)buttonPressed:(NSButton *)sender {
       strcpy(cstr, "Application must quit");
    
    现在,cstr始终存在,因此块副本的地址始终有效

    当然,您现在也永久性地使用了256字节的内存,如果这个字符串只需要很短的时间,那就是一个(小的)浪费

    在您的实际代码中,这可能不是一个问题-C字符串可能已经被管理,所以它们可以根据需要使用多长时间。如果不需要并且需要使用C字符串,那么您可能需要考虑动态分配它们(请参见
    malloc
    和friends),并在不再需要时释放它们(请参见
    free


    HTH

    为什么要使用C字符串?感谢您对变量生存期的评论。我尽量避免使用全局变量,除非必要。事实上,将字符串声明为static char cstr[256];解决了这个问题。这只是为了测试和演示的目的。在real应用程序中,它有点复杂。尽管如此,256字节在应用程序的生命周期中仅使用一次,如果有的话。函数内声明中的Yes
    static
    也会起作用-这会将生命周期更改为整个程序执行,就像全局一样,但会将名称的可见性限制在函数内。