【问题标题】:spurious, intermittent, variable undefined error虚假的、间歇性的、可变的未定义错误
【发布时间】:2017-12-24 09:16:23
【问题描述】:

我最近在一个 CFC 中创建了这个函数,它被实例化到应用程序范围中:

Public String function url_for(path='') {
    var results = '';
    var these_parms = '';
    var parm_delim = '?';
    for (key in Arguments) {
        if (len(Arguments[key])) {
            switch(key) {
                case "path":
                    results = '#arguments[key]#';
                    break;
                case "template":
                    results = '/cf/#arguments[key]#';
                    break;
                case "productid":
                    if (NOT comparenocase(left(arguments[key],2),'p_'))
                        results = real_url_for(partno=replace(arguments[key],'p_',''));
                    else
                        results = real_url_for(productid=arguments[key]);
                    break;
                case "categoryid":
                    results = real_url_for(categoryid=arguments[key]);
                    break;
                case "specialid":
                    results = real_url_for(specialid=arguments[key]);
                    break;
                case "partno":
                    if (NOT len(arguments['path']))
                        results = real_url_for(partno=arguments[key]);
                    else
                        these_parms = listappend(these_parms,'#key#=#urlencodedformat(arguments[key])#','&');
                    break;
                case "parms":
                    these_parms = listappend(these_parms,'#arguments[key]#','&');
                    break;
                default:
                    these_parms = listappend(these_parms,'#key#=#urlencodedformat(arguments[key])#','&');
                    break;
            }
        }
    }
    if (len(results)) { //*********** error always occurs here 
        for (var i=1;i LTE variables.rewritequery.recordcount;i=i+1) {
            if (NOT comparenocase(variables.rewritequery.internalurl[i], results)) {
                results = variables.rewritequery.externalurl[i];
                break;
            }
        }
    }
    if (len(results) AND len(these_parms)) {
        if (listlen(results,'?') GT 1)
            parm_delim = '&';
        results = listappend(results, these_parms, parm_delim);
    }
    return results;
}

它每小时运行数百或数千次,有时在同一个请求中运行数十次,但每隔几个小时左右就会抛出一个错误(总是在上面代码中标记的行):变量结果未定义

我无法检测到它被抛出的时间、方式或原因。发生错误时使用的相同输入将在几秒钟后正常工作。主要是,我看不出它应该如何被抛出。

我认为被调用的函数 (real_url_for) 可能返回未定义的值,但它具有相同的 var results='';,并且该变量就是它返回给该函数的值。

不知道这是否相关,但 application.cfm 文件定义了一个包装函数 app_url_for(),它只是调用并返回此函数的值。这是为了避免到处引用Application.URLManager.url_for()

这让我很难过。我想我可以检查变量是否存在,但应该没有必要这样做。

这里是real_url_for 函数:

Private String function real_url_for() {
    var results = '';
    for (key in Arguments) {
        if (len(Arguments[key])) {
            switch(key) {
                case "productid":
                    results = '/cf/displaylearnmore.cfm?#key#=#arguments[key]#';
                    break;
                case "categoryid":
                    results = '/cf/learnmorelist.cfm?#key#=#arguments[key]#';
                    break;
                case "specialid":
                    results = '/cf/displayspecial.cfm?#key#=#arguments[key]#';
                    break;
                case "partno":
                    results = '/part/#arguments[key]#';
                    break;
            }
        }
    }
    return results;
}

我会尝试将var key=''; 添加到这两个函数中,看看是否有帮助。

【问题讨论】:

  • 由于变量泄漏,听起来像是竞态条件。浏览代码我看到至少一个不是 var 作用域的变量:key。首先检查调用的函数并验证所有函数局部变量都已本地化。
  • 你能告诉我们real_url_for中的代码吗?变量泄漏(至少在url_for 中)不能解释问题,但@Ageax 仍然是正确的。
  • 您有各种名称相同的变量,并且您正在循环两个不同的 Arguments 范围。这很容易导致泄漏。我建议首先重命名循环计数器(即 for (k in.. 和 `for (q in...) 并查看是否会更改错误。您还可以在开关中添加一些故障排除信息,以查看具体的选项发生错误。此外,您是否会将多个选项传递给这些函数中的任何一个?如果没有,请完全放弃循环并使用实际的 Argument 而不是范围。循环一个项目有点毫无意义。
  • @JoeCopley variables.rewritequery 来自哪里?

标签: coldfusion coldfusion-10 cfc


【解决方案1】:

由于可变泄漏,听起来像是竞态条件。浏览代码我看到至少一个不是 var 作用域的变量:key。由于组件存储在application 范围内,多个线程很容易同时读取/写入该变量,从而导致错误或奇怪的结果。

首先检查调用的函数。验证所有函数局部变量都已正确本地化。

【讨论】:

    【解决方案2】:

    key 变量声明为每个函数的本地变量似乎已经解决了这个问题。四天多没有复发。感谢所有提供反馈的人。

    【讨论】:

    • 变量泄漏可能很难解决,尤其是如果您不是代码的原始作者。这就是为什么良好的范围界定很重要。很高兴你把它修好了。
    猜你喜欢
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 2014-02-17
    • 1970-01-01
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 2015-08-11
    相关资源
    最近更新 更多